独闷闷网

 找回密码
 立即注册
搜索
查看: 13319|回复: 5
收起左侧

[原创] 浅谈C51之位变量

[复制链接]
发表于 2015-2-17 16:21:17 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
本帖最后由 不是盖的 于 2015-2-17 16:21 编辑

         对于从C51入门学习51单片机的初学者来说,对于位变量很多感到疑惑。位变量的定义对应什么内存,其操作特点是什么,跟普通的变量有什么区别。基于此,个人整理归纳发表此帖,表述不当或有误之处,欢迎批评指正。
        要具体了解位变量,我们还得从51内存结构入手,我们以8051为例。
                                                         1.png
                                                                           
         在片内,数据存储区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,还为每个位编排位寻址地址,如下图。
                                                       2.jpg
      位寻址区第一单元的地址是20H,从其最低位开始位编址。
      即位寻址区第一单元的最低位的位编址是00H,第二位是01H,第三位是02H        。。。。。。。最高位即第8位是07H。
      同样道理,寻址区第二单元的8个位对应的8个位编址是  08H,09H,0AH,0BH,0CH,0DH,0EH,0FH。如此类推。
      这样,位寻址区的16字节单元,每个字节有他的地址外,每个字节的每个位也有他对应的位编址。我们可以以字节访问,也可以以位为单元进行访问。
      除了位寻址区的位有位编址外,特殊功能区,凡是地址为8的倍数的特殊功能寄存器其每一位都有位编址。如下图
                                                                              3.jpg
                                                                              4.jpg   
              
         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; 我们编写一段代码验证一下。
                                                                            代码.jpg
                                           看一下他对应的汇编,没学过汇编的同学大概了解一下。
                                                                                  汇编.jpg
        从汇编代码我们可以知道,bdata 类型的变量bd系统分配的内存单元是20H,bit1分配的单元是21H的第一位,bit2分配的内存单元是21H的第二位,我们通过bd0,bd1访问变量bd的第一位和第二位。代码运行之后,我们查看其内存变化结果。
                                                         内存.jpg
             大家可以看得到,0x20单元的结果为0XFC,0x21单元运行完之后的结果是0X03,大家自己去理解解释,结果是验证我们之前的论述的。
              那么,位变量优点何在。位变量可以高效操作一个位单元。 如一下代码
                                                                           LED.jpg
            把P0寄存器第一位置1,其对应的汇编代码我们看一下,

                                                                         LED汇编.jpg
           很简单,就一单周期的指令就完成了。
           如果是普通变量,我们我们想把第一位置1,怎么做,如一下代码
                                                                普通变量.jpg

           我们查看一下他对应的汇编,
                                                          普通汇编.jpg

         相比之下,其代码效率与运行效率都远不及位变量操作。   
         运用技巧:在编程中需要诸多标志位,比如8个,一种办法是定义8个unsigned char变量,这个办法简单,但比较笨,也耗内存,运行效率也不高,比如你要操作多个标志,就得一个个去操作。 其二是定义一个unsingned char 变量,8个位每一个位对应一个标志,用或与操作。对于51这种有位寻址的单片机,自然是首选位操作,简洁又高效。当然,他的缺点也是很明显,移植不便。          个人见解,表述不当或有误之处,欢迎批评指正。谢谢!!!!!














   


     

                                      



               
         




代码.jpg
4.jpg
乐于分享,勇于质疑!
发表于 2015-2-20 14:13:23 | 显示全部楼层
我刚刚花了20分钟仔细读完。非常精彩。获益很多。
乐于分享,勇于质疑!
发表于 2015-2-20 15:50:04 | 显示全部楼层
写的太好了{:soso__3409329614010722382_4:}
乐于分享,勇于质疑!
发表于 2015-3-2 22:35:53 | 显示全部楼层
学习了                             
乐于分享,勇于质疑!
发表于 2015-3-24 20:27:09 来自手机 | 显示全部楼层
又见高人
乐于分享,勇于质疑!
回复

使用道具 举报

发表于 2015-4-26 17:41:54 | 显示全部楼层
高人啊,学习了
乐于分享,勇于质疑!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|独闷闷网 ( 粤ICP备12007667号-2 )

GMT+8, 2024-3-29 13:29 , Processed in 0.185353 second(s), 20 queries .

快速回复 返回顶部 返回列表