您的位置 首页 资料

单片机C言语位操作实例

C语言本身有较强的位处理功能,但在控制领域有时候经常需要控制某一个二进制中的某一位,为此在MCS_51的KEILC51中扩充了两个数据类型bit

C言语自身有较强的位处理功用,但在操控范畴有时分常常需求操控某一个二进制中的某一位,为此在MCS_51的KEIL C51中扩大了两个数据类型bit和sbit。前者能够在MCS_51的位寻址区进行分配,而后者只能界说为可位寻址的特别功用寄存器SFR中的某一位。这两个扩大为MCS_51运用C言语编程带来很大的便利。AVR的C言语中除了CodeVisionAVR界说了bit数据类型外,其他都没有相似的界说,而sbit类型一切C言语都没有界说。相比较,进行位操作运算CodeVisionAVR的功用最强,它一方面有bit类型的数据,可用于位运算;另外在拜访寄存器时能够直接拜访寄存器的某一位,例如拜访DDRB的B2位能够这样拜访:

DDRB.3 = 1;
而在IAR、ICCAVR和GCCAVR中没有bit类型的运算,当它们需求拜访寄存器的某一位时,只能运用ANSI C言语的位运算功用。
C言语是为描绘体系而规划,因而它具有汇编言语所能完结的一些功用,有较好的位操作指令:“&”,“|”,“~”、“<<”、“>>”。在操控范畴,常常需求操控某一个二进制位,规范C有两种办法完成单个位的操作。
1. 用“读-修正-写”完成对单个位的操作
在没有单个位的位操作指令的情况下,一般是选用“读-修正-写”的办法完成单个位的位操作,即:
Ø 经过与0“与”操作,将某一位清0。例如,使i变量的第0位为0,完成办法为:i = i&0xfe;
Ø 经过与1相 “或”操作,将某一方位1。例如,使i变量的第0位为1,完成办法为 i = i|0x01;
Ø 经过与1进行“异或”操作,将某一位取反。例如,使i变量的第0位取反,完成办法为 i = i^0x01。
留意:选用“读-修正-写”的办法时不要影响其他位。即某位清0时,其他位与1相 “与”;某方位1时,其他位与0“或”;取反时,其他位与0“异或”。
许多程序员喜爱选用下面的移位办法,句子简练:
#define bit(x) (1<<(x))
#define LED 2
PORTB|= bit(LED); //将PORTB第二方位1,点亮连接在I/O口的LED
该办法下,程序运转时会添加移位操作,生成的代码较大。若按如下办法直接界说生成的代码就不会有移位操作:
#define LED 0X04
PORTB |= LED;
也有程序员采纳如下宏界说的办法完成单个位的操作,运用非常便利:
#define SET_BIT(x,y) ((x)|=(0x0001<<(y)))//置x的第y位
#define CLR_BIT(x,y) ((x)&=~( 0x0001<<(y)))//清x的第y位为0 #define CPL_BIT(x,y) ((x)^= (0x0001<<(y)))//取反x的第y位
#define GET_BIT(x,y) (((x)&(1<读取x的第y位
#define LET_BIT(x,y,z) ((x)=(x)&(~(1<<(y)))|((z)<<(y)))//
将x的第y位写上z(0/1)
2. 经过位域的(Bit Field )的办法完成位操作
在体系寄存器设置时,许多时分并不需求修正完好的字节,而是只修正一个或几个位,规范C供给了一种根据结构体的数据结构——位域。位域便是把一个存储单元中的二进制划分为几个不同的区域,并阐明每个区域的位数,每个域有一个域名,答应在程序中按域名进行操作。位域的界说格局如下:
Struct 位域结构名
{
位域列表;
};
位域列表格局为:类型阐明符 位域名:位域长度
Struct k
{
unsigned int a:1;
unsigned int :2;
unsigned int b:3;
unsigned int :0;//空域
}k1;
阐明:
Ø 各位顺次从低位到高位摆放,排满一个存储单元,按地址接着排下一个单元。
Ø 位域能够无域名,但不能被引证。例如,第2域,这时它只用来填充和调整方位。
Ø 第四行称为空域,意图是将现在存储单元的剩下部分分为一个域,且填充0。
位域的引证,例如;
k1.a = 1;//置k1的BO位为1
k1.b = 7;//置k1的B3-B5位为111
用位域界说位变量,操作I/O口,发生的代码紧凑、高效。界说的办法如下;
typedef struct INT8_bit_struct
{
unsigned bit0:1; unsigned bit1:1; unsigned bit2:1;
unsigned bit3:1; unsigned bit4:1; unsigned bit5:1;
unsigned bit6:1;unsigned bit7:1;
}bit_field;
再次宏界说每一个位,运用办法如下:
#define _PINB 0x23
#define _PORTB 0X25
…………
#define IOB2i (*(volatile bit_field *)(_PINB)).bit2
#define IOB2o (*(volatile bit_field *)(_PORTB)).bit2
例如:
void main(void)
{
unsigned char I;
IOB2o = 0;//B口B2位输出低电平
i = IOB2i;//读B口B2位,将B口B2位上的电平值送给i
//
}
关于没有扩展位变量的C言语环境,在汇编下没有单个位的位操作的MCU,经过位域的办法操作I/O口是最佳的办法;汇编下有单个位的位操作指令的MCU,能够嵌入式汇编,可是程序的移植性可能会下降,主张运用位域的办法进行操作比较适宜。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/ziliao/259887.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部