今天介绍一下在单片机开发中,经常用到的位操作的一些方法和技巧,熟练掌握位操作的方法,在开发过程中,特别是在对寄存器读写时,起到事半功倍的作用,本文介绍几种位操作的宏定义,来帮助我们进行位操作。
<1> BIT(x)
#define BIT(x) ( (uint32_t) 0x1 << x ) // 将0x1左移x位, 使第x位置1
它用于实现使一个变量的第x位置1,本文所有的变量都是以32位无符号数为例。
BITS(4),BITS(8)的实现过程如下图,将0x01用二进制方式表示出来,其第0位为1,现在将其左移4位,得到的数据就是BIT(4)的值,如果将其左移8位,得到的数据就是BIT(8)的值,将BIT(4)和BIT(8)的值相加,得到二者之和,此和之中第8位和第4位被置1。

举例说明一下BIT(X)的使用:
例1:定义一个变量val,需要将val的第8位和第4位置1, 且其他位不能受影响,那么可以用此语句完成:
uint32_t val;
Val |= BIT(8) + BIT(4);
其实现过程如下图,将val用二进制方式表示出来,val的值不确定,用X来代替,

根据前面计算得到的BIT(8)和BIT(4)的和,将这2个数据进行或运算,0或X的值始终是X,1或X的值始终是1,得到最终的结果中只有第8位和第4位变成了1,其他位保持不变。
例2:如需要将val的第16位和第8位置0, 且其他位不能受影响,那么可以用此语句完成:
Val &= ~( BIT(16) + BIT(8) );
其实现过程如下图,将val用二进制方式表示出来,val的值不确定,用X来代替

将BIT(16)和BIT(8)的和值取反,将取反的结果和val原值进行与运算,1与X的值始终是X,0与X的值始终是0,得到最终的结果中只有第16位和第8位变成了0,其他位保持不变。
<2> BITS(start, end)
#define BITS(start, end) ( (0xFFFFFFFFU << (uint32_t)start) & (0xFFFFFFFFU >> (31U - (uint32_t)end)) )
这个宏定义是用来实现从低位start到高位end之间所有的位置1。
BITS(4, 7)的实现过程如下图:

提供一个32位数据,其所有位均为1,将此数据左移start位,也就是4位,得到左移4位后的结果,再将一个所有位均为1的32位数据,右移31-end位,也就是24位,得到右移24位后的结果,将左移和右移的结果进行与运算,只有1与1的值是1,0与其他均为0,与运算结果中第4到第7位为1,其他均为0。
举例说明一下BITS(start, end)的使用:
例1:将val的第4位至第7位置1, 且其他位不能受影响,那么可以用此语句完成:
uint32_t val;
Val |= BITS(4,7);
其实现过程如下图:

将val用二进制方式表示出来,根据刚才计算得到的BITS(4, 7)的值,将BITS(4, 7)的值和val原值进行或运算,根据或运算规则,最终的结果中只有第4位至第7位被置为1,其他位不变化。
例2:将val的第4位至第7位置0, 且其他位不能受影响,那么可以用此语句完成:
Val &= ~BITS(4,7);
其实现过程如下图:

将val用二进制方式表示出来,这是刚才计算得到的BITS(4, 7)的值,将其取反,将取反后的BITS(4, 7)的值和val原值进行与运算,根据与运算规则,最终的结果中只有第4位至第7位被置为0,其他位不变化。
<3> BITS_SET(x, val)
#define BITS_SET(x, val) ( (uint32_t)( (uint32_t)val << x ) )
这个宏定义是用来实现从低位x开始设置数值Val
BITS_SET(4, 0x32)的实现过程:

将0x32用二进制方式表示出来,左移4位,得到结果。
<4> BITS_GET(start, end, val)
#define BITS_GET(start, end, val) ( ( val & BITS(start, end) ) >> start )
这个宏定义是用来实现从变量val中获取,从低位start到高位end的数据,并将结果右对齐。
BITS_GET(4, 7, val)的实现过程:

将val用二进制方式表示出来,根据前面计算得到的BITS(4, 7)的值,将这2个数据进行与运算,根据与运算规则,最终的结果中只有第4位至第7位被保留,其他位均为0,将此结果右移4位,得到右对齐的最终结果。
1245

被折叠的 条评论
为什么被折叠?



