专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
51单片机
浅谈C51之位变量
2019-07-15 17:48
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
51单片机
10050
2
1292
本帖最后由 不是盖的 于 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 */
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,大家自己去理解解释,结果是验证我们之前的论述的。
那么,位变量优点何在。位变量可以高效操作一个位单元。 如下代码
很简单,就一条单周期的指令就完成了。
如果是普通变量,我们想把第一位置1,怎么做,如下代码
我们查看一下他对应的汇编。
普通变量实现单独操作某一位,是要读改写三步实现的。其代码效率与运行效率都远不及位变量操作。
运用技巧:在编程中需要诸多标志位,比如8个,一种办法是定义8个unsigned char变量,这个办法简单,但比较笨,也耗内存,运行效率也不高,比如你要操作多个标志,就得一个个去操作。 其二是定义一个unsingned char 变量,8个位每一个位对应一个标志,用或与操作。而对于51这种有位寻址的单片机,自然是首选位操作,简洁又高效。
当然,他的缺点也是很明显,移植不便。
个人见解,表述不当或有误之处,欢迎批评指正。谢谢!!!!!
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
2条回答
不是盖的
2019-07-15 23:15
本帖最后由 不是盖的 于 2015-2-19 12:06 编辑
xouou 发表于 2015-2-18 18:16
#ifndef _C51
#define _bit unsigned char
#else
#ifndef _C51
typedef unsigned char bit
#endif
这样比较简洁吧
加载中...
查看其它2个回答
一周热门
更多
>
相关问题
【东软载波ESF0654 PDS开发板活动】开箱
1 个回答
东软载波ESF0654 PDS开发板外部中断
1 个回答
东软载波ESF0654 PDS开发板高级控制定时器AD16C4T
1 个回答
用串口调试助手为什么只能在hex模式接收发送而在文本模式不行
9 个回答
触摸芯片SC02B/SC04B在地砖灯的设计方案
1 个回答
相关文章
51单片机与蓝牙模块连接
0个评论
51单片机的硬件结构
0个评论
基于51单片机的无线遥控器制作
0个评论
51单片机 AD转换
0个评论
51单片机数码管递增显示
0个评论
如何实现对单片机寄存器的访问
0个评论
基于51单片机的指纹密码锁
0个评论
×
关闭
采纳回答
向帮助了您的知道网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
51单片机
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
×
付费偷看金额在0.1-10元之间
确定
×
关闭
您已邀请
0
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
#ifndef _C51
typedef unsigned char bit
#endif
这样比较简洁吧
一周热门 更多>