浅谈C51之位变量
本帖最后由 不是盖的 于 2015-2-17 16:21 编辑对于从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 */
sbit CY = 0xD7;
sbit AC = 0xD6;
sbit F0 = 0xD5;
sbit RS1= 0xD4;
sbit RS0= 0xD3;
sbit OV = 0xD2;
sbit P = 0xD0;
/*TCON*/
sbit TF1= 0x8F;
sbit TR1= 0x8E;
sbit TF0= 0x8D;
sbit TR0= 0x8C;
sbit IE1= 0x8B;
sbit IT1= 0x8A;
sbit IE0= 0x89;
sbit IT0= 0x88;
/*IE */
sbit EA = 0xAF;
sbit ES = 0xAC;
sbit ET1= 0xAB;
sbit EX1= 0xAA;
sbit ET0= 0xA9;
sbit EX0= 0xA8;
/*IP */
sbit PS = 0xBC;
sbit PT1= 0xBB;
sbit PX1= 0xBA;
sbit PT0= 0xB9;
sbit PX0= 0xB8;
/*P3*/
sbit RD = 0xB7;
sbit WR = 0xB6;
sbit T1 = 0xB5;
sbit T0 = 0xB4;
sbit INT1 = 0xB3;
sbit INT0 = 0xB2;
sbit TXD= 0xB1;
sbit RXD= 0xB0;
/*SCON*/
sbit SM0= 0x9F;
sbit SM1= 0x9E;
sbit SM2= 0x9D;
sbit REN= 0x9C;
sbit TB8= 0x9B;
sbit RB8= 0x9A;
sbit TI = 0x99;
sbit RI = 0x98;
说到这里,总结就一句话,位寻址区与地址为8倍数的特殊功能寄存器的每个字节单元有地址外,每个字节的每一位也有他的位编址。
我们可以以字节为单元进行访问,也可以以1位为单元进行访问。接下来我们来讲位变量操作和他的优点。
在C51中用bit 和sbit定义位变量,bit 定义的变量是由编译器分配的,如果你想通过该位变量操作特定的内存,就可以用sbit,如我们re g51.h中定义的sbit TF1= 0x8F;0x8F就是位编址,通过TF1就能访问0x8F这个位单元。或者我们经常用的
sbit LED =P0^0; 我们编写一段代码验证一下。
看一下他对应的汇编,没学过汇编的同学大概了解一下。
从汇编代码我们可以知道,bdata 类型的变量bd系统分配的内存单元是20H,bit1分配的单元是21H的第一位,bit2分配的内存单元是21H的第二位,我们通过bd0,bd1访问变量bd的第一位和第二位。代码运行之后,我们查看其内存变化结果。
大家可以看得到,0x20单元的结果为0XFC,0x21单元运行完之后的结果是0X03,大家自己去理解解释,结果是验证我们之前的论述的。
那么,位变量优点何在。位变量可以高效操作一个位单元。 如一下代码
把P0寄存器第一位置1,其对应的汇编代码我们看一下,
很简单,就一单周期的指令就完成了。
如果是普通变量,我们我们想把第一位置1,怎么做,如一下代码
我们查看一下他对应的汇编,
相比之下,其代码效率与运行效率都远不及位变量操作。
运用技巧:在编程中需要诸多标志位,比如8个,一种办法是定义8个unsigned char变量,这个办法简单,但比较笨,也耗内存,运行效率也不高,比如你要操作多个标志,就得一个个去操作。 其二是定义一个unsingned char 变量,8个位每一个位对应一个标志,用或与操作。对于51这种有位寻址的单片机,自然是首选位操作,简洁又高效。当然,他的缺点也是很明显,移植不便。 个人见解,表述不当或有误之处,欢迎批评指正。谢谢!!!!!
我刚刚花了20分钟仔细读完。非常精彩。获益很多。 写的太好了{:soso__3409329614010722382_4:} 学习了 又见高人 高人啊,学习了
页:
[1]