一、操作位的方法操作位有两种方法,一种是位字段,另一种是使用按位运算符。 本文介绍使用按位运算符操作位的方法。下表为几种位操作符及其含义:

二、不改变其他位的值的状况下,对某几个位进行设值。在嵌入式编程中,常常需要对一些寄存器进行配置,有的情况下需要改变一个字节中的某一位或者几位,但是又不想改变其它位原有的值,这时就可以使用按位运算符进行操作。下面进行举例说明,假如有一个8位的TEST寄存器:

当我们要设置第0位bit0的值为1时,可能会这样进行设置:
TEST 0x01
但是,这样设置是不够准确的,因为这时候已经同时操作到了高7位:bit1~bit7,如果这高7位没有用到的话,这么设置没有什么影响;但是,如果这7位正在被使用,结果就不是我们想要的了。在这种情况下,我们就可以借用&和|进行配置。
对于二进制位操作来说,不管该位原来的值是0还是1,它跟0进行&运算,得到的结果都是0,而跟1进行&运算,将保持原来的值不变;不管该位原来的值是0还是1,它跟1进行|运算,得到的结果都是1,而跟0进行|运算,将保持原来的值不变。
所以,此时可以设置为:
TEST TEST 0x01
其意义为:TEST寄存器的高7位均不变,最低位变成1了。在实际编程中,常改写为:TEST 0x01
这种写法可以一定程度上简化代码,是 C 语言常用的一种编程风格。同样的,要给TEST的低4位清0,高4位保持不变,可以进行如下配置:
TEST 0xF0
这个场景嵌入式开发中经常使用,方法就是先对需要设置的位用&操作符进行清零操作,然后用|操作符设值。比如我要改变GPIOA的状态,可以先对寄存器的值进行&清零操作:GPIOA>&= ;
然后再与需要设置的值进行|或运算:GPIOA>|= ;
移位操作提高代码的可读性。移位操作在单片机开发中也非常重要,下面让我们看看固件库的GPIO初始化的函数里面的一行代码:
-BSRR ((uint32_t0x01<< pinpos;
这个操作就是将BSRR寄存器的第pinpos位设置为1,为什么要通过左移而不是直接设置一个固定的值呢?其实,这是为了提高代码的可读性以及可重用性。这行代码可以很直观明了的知道,是将第pinpos位设置为1。如果你写成:-BSRR 0x0030
这样的代码就不好看也不好重用了。类似这样的代码很多:
GPIOA>|= << ;
这样我们一目了然,5告诉我们是第5位也就是第6个端口,1告诉我们是设置为1了。三、~取反操作使用技巧SR寄存器的每一位都代表一个状态,某个时刻我们希望去设置某一位的值为0,同时其他位都保留为1,简单的作法是直接给寄存器设置一个值:
-SR 0xFFF7;
这样的作法设置第3位为0,但是这样的作法同样不好看,并且可读性很差。看看库函数代码中怎样使用的:-SR (uint16_t~;
而TIM_FLAG 是通过宏定义定义的值:TIM_FLAG_Update (uint16_t0x0001#define TIM_FLAG_CC1 ((uint16_t)0x0002)#define TIM_FLAG_CC2 ((uint16_t)0x0004)#define TIM_FLAG_CC3 ((uint16_t)0x0008)#define TIM_FLAG_CC4 ((int16_t)0x0010)#define TIM_FLAG_COM ((uint16_t)0x0020)#define TIM_FLAG_Trigger ((uint16_t)0x0040)#define TIM_FLAG_Break ((uint16_t)0x0080)#define TIM_FLAG_CC1OF ((uint16_t)0x0200)#define TIM_FLAG_CC2OF ((uint16_t)0x0400)#define TIM_FLAG_CC3OF ((uint16_t)0x0800)#define TIM_FLAG_CC4OF ((uint16_t)0x1000)
即设置SR第3位为0时可设置为:
-SR (uint16_t~;
以上就是关于位操作在嵌入式编程中的一些技巧,如有错误,欢迎指出! |