1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本帖最后由 不是盖的 于 2015-2-18 12:34 编辑 对于从C51入门学习51单片机的初学者来说,对于位变量很多感到疑惑。位变量的定义对应什么内存,其操作特点是什么,跟普通的变量有什么区别。基于此,个人整理归纳发表此帖,表述不当或有误之处,欢迎批评指正。 要具体了解位变量,我们还得从51内存结构入手,我们以8051为例。 在片内,数据存储区RAM与特殊功能寄存器区SFR统一编址。地址00H 到7FH总共128单元是数据存储区RAM,地址80H到FFH总共128单元是特殊功能寄存器区。 数据存储区RAM128个单元分为3部分 其一是通用寄存器区,其地址为00H到1FH,共32字节单元。 其二是位寻址区,其对应的地址是20H到2FH,共16字节单元,我们定义的bit的位变量或者bdata修饰的变量,其分配的内存就是在这16字节的位寻址区,也就是说,我们最多能定义128(8*16)个位变量。 其三是用户RAM区,其地址为30H到7FH,我们定义的除了bit和bata其他变量,堆栈等都在这80字节单元内存里分配。 我们这里重点讲一下位寻址区。位寻址区每个单元除了系统统一编排的地址外,如上面的20H到1FH,还为每个位编排位寻址地址,如下图。 位寻址区第一单元的地址是20H,从其最低位开始位编址。 即位寻址区第一单元的最低位的位编址是00H,第二位是01H,第三位是02H .......最高位即第8位是07H。 同样道理,寻址区第二单元的8个位对应的8个位编址是 08H,09H,0AH,0BH,0CH,0DH,0EH,0FH。如此类推。 这样,位寻址区的16字节单元,每个字节有他的地址外,每个字节的每个位也有他对应的位编址。我们可以以字节访问,也可以以位为单元进行访问。除了位寻址区的位有位编址外,特殊功能区,凡是地址为8的倍数的特殊功能寄存器其每一位都有位编址。如下图 P0寄存器的地址是80H,地址是8的倍数,每一位都有他的位编址,最低位为80H,第二位为81H,第三位为82H, 。。。。 同样的道理,定时器计数控制寄存器Tcon的地址为88H,他的第一位IT0的位编址是88H,第二位IEO的位编址是89H。。。。 我们看可以在reg51.h看到他们相应的位定义。 /* BIT Register */ /* PSW */ ***it CY = 0xD7; ***it AC = 0xD6; ***it F0 = 0xD5; ***it RS1 = 0xD4; ***it RS0 = 0xD3; ***it OV = 0xD2; ***it P = 0xD0; /* TCON */ ***it TF1 = 0x8F; ***it TR1 = 0x8E; ***it TF0 = 0x8D; ***it TR0 = 0x8C; ***it IE1 = 0x8B; ***it IT1 = 0x8A; ***it IE0 = 0x89; ***it IT0 = 0x88; /* IE */ ***it EA = 0xAF; ***it ES = 0xAC; ***it ET1 = 0xAB; ***it EX1 = 0xAA; ***it ET0 = 0xA9; ***it EX0 = 0xA8; /* IP */ ***it PS = 0xBC; ***it PT1 = 0xBB; ***it PX1 = 0xBA; ***it PT0 = 0xB9; ***it PX0 = 0xB8; /* P3 */ ***it RD = 0xB7; ***it WR = 0xB6; ***it T1 = 0xB5; ***it T0 = 0xB4; ***it INT1 = 0xB3; ***it INT0 = 0xB2; ***it TXD = 0xB1; ***it RXD = 0xB0; /* SCON */ ***it SM0 = 0x9F; ***it SM1 = 0x9E; ***it SM2 = 0x9D; ***it REN = 0x9C; ***it TB8 = 0x9B; ***it RB8 = 0x9A; ***it ti = 0x99; ***it RI = 0x98; 说到这里,总结就一句话,位寻址区与地址为8倍数的特殊功能寄存器的每个字节单元有地址外,每个字节的每一位也有他的位编址。 我们可以以字节为单元进行访问,也可以以1位为单元进行访问。接下来我们来讲位变量操作和他的优点。 在C51中用bit 和***it定义位变量,bit 定义的变量是由编译器分配的,如果你想通过该位变量操作特定的内存,就可以用***it,如我们re g51.h中定义的***it TF1 = 0x8F; 0x8F就是位编址,通过TF1就能访问0x8F这个位单元。或者我们经常用的 ***it LED =P0^0; 我们编写一段代码帮助理解一下。 看一下他对应的汇编,没学过汇编的同学大概了解一下。 从汇编代码我们可以知道,bdata 类型的变量bd系统分配的内存单元是20H,bit1分配的单元是21H的第一位,bit2分配的内存单元是21H的第二位,我们通过bd0,bd1访问变量bd的第一位和第二位。代码运行之后,我们查看其内存变化结果。 大家可以看得到,0x20单元的结果为0XFC,0x21单元运行完之后的结果是0X03,大家自己去理解解释,结果是验证我们之前的论述的。 那么,位变量优点何在。位变量可以高效操作一个位单元。 如下代码 很简单,就一条单周期的指令就完成了。 如果是普通变量,我们想把第一位置1,怎么做,如下代码 我们查看一下他对应的汇编。 普通变量实现单独操作某一位,是要读改写三步实现的。其代码效率与运行效率都远不及位变量操作。 运用技巧:在编程中需要诸多标志位,比如8个,一种办法是定义8个unsigned char变量,这个办法简单,但比较笨,也耗内存,运行效率也不高,比如你要操作多个标志,就得一个个去操作。 其二是定义一个unsingned char 变量,8个位每一个位对应一个标志,用或与操作。而对于51这种有位寻址的单片机,自然是首选位操作,简洁又高效。当然,他的缺点也是很明显,移植不便。个人见解,表述不当或有误之处,欢迎批评指正。谢谢!!!!!
|
|
相关推荐
2个回答
|
|
|
|
|
|
本帖最后由 不是盖的 于 2015-2-19 12:06 编辑
#ifndef _C51 typedef unsigned char bit #endif 这样比较简洁吧 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
205 浏览 0 评论
求助一下关于51系列单片机的Timer0的计时问题,TH0、TL0+1的时间是怎么算的?
1253 浏览 1 评论
【RA-Eco-RA4E2-64PIN-V1.0开发板试用】开箱+Keil环境搭建+点灯+点亮OLED
848 浏览 0 评论
【敏矽微ME32G070开发板免费体验】使用coremark测试敏矽微ME32G070 跑分
853 浏览 0 评论
【敏矽微ME32G070开发板免费体验】开箱+点灯+点亮OLED
1073 浏览 2 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
12012 浏览 31 评论
小黑屋| 手机版| Archiver| 德赢Vwin官网 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 01:35 , Processed in 0.474563 second(s), Total 44, Slave 37 queries .
Powered by 德赢Vwin官网 网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号