今天跟着视频学习了位运算,感觉很有用,这里分享给大家。
位运算
位运算主要有:位与运算符(&)、按位或运算符(|)、异或运算符(^)、取反运算符(~)、左移运算符(<<)、右移运算符(>>)等,下面我们分别介绍这几个位运算的用法及其在程序中的运用。
(1)位与(&)
按位与运算符“&”是双目运算符。其功能是参与运算的两数各对应的二进位相与。两个数相“与”时,如果两个位同时为1,则结果为1,否则为0,即:1&1=1,1&0=0,0&1=0,0&0=0。
比如:0xc3&0x11计算如下
在STM32编程中位与(&)运算可以作为条件判断之用,请看下面的程序:
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin),这是STM32库中的函数,用来读取输出的某个引脚的电平,运行一下”Go To Definition”,你会发现下面的语句:
if ((GPIOx->ODR & GPIO_Pin) != (uint32_t)Bit_RESET),当然对应的GPIOx->ODR是输出数据寄存器的值,是16位的数值;GPIO_Pin也是STM32库定义的16位类型的数据。
(2)位或(|)
按位或运算符“|”是双目运算符。其功能是参与运算的两数各对应的二进位相或。只要对应的两个二进位有一个为1时,结果位就为1,即:1|1=1,1|0=1,0|1=1,0|0=0。
比如:0xc3|0x10
在STM32编程中位或运算(|),可以作为置位之用,因为位或运算不会改变影响原来数值的其它位,上面的0xc3|0x10,原来的0xc3(b11000011),只有一个位发生了改变。请看下面的程序:
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0|GPIO_Pin_1;这是常见的对两个引脚按位或,在STM32库中,GPIO_Pin_0和GPIO_Pin_1其实也是两个整数,请看它们的宏定义:
#define GPIO_Pin_0 ((uint16_t)0x0001)
#define GPIO_Pin_1 ((uint16_t)0x0002)
(3)异或(^)
两个二进制数进行异或,若对应的位不相同,则结果为1,否则为0,即:0^0=0,0^1=1,1^0=1,1^1=0;
比如(0xc3 ^ 0x10) ^ 0x10
从上面的式子中大家发现了什么,对,0xc3与0x10第一次异或,发生一次改变,且只改变了与0x10相关的位,并且如果与同一个数两次异或,它就恢复到初始值,所以异或(^)具有翻转的功能,在程序中可以当做开关使用,比如,让一个LED灯点亮和熄灭就可以用这种方法:
GPIOA->ORD ^= GPIO_Pin_1; //LED1灯熄灭
Delay_ms(100);
GPIOA->ORD ^= GPIO_Pin_1; //LED1点亮
(4)取反(~)
这是个单目运算符,二进制位取反,如果1取反,结果为0,0取反,结果为1,即:~0=1,~1=0。
程序中取反(~)和按位与(&)相结合,会有复位的效果。
比如0xd3&(~0x10)
(~0x10)结果为b11101111,再和0xc3按位与:
是不是达到了复位的效果呢?
(5)左移运算符(<<)
左移运算符用来将一个数的各二进制位全部左移若干位,后面补0,移出的位被丢弃,相当于乘2运算,因为位运算比乘法用算快,所以可对一个代码进行优化。
比如0x01<<8,结果为b100000000,就是1后面补8个0,移位运算符在通信时,接收数据时很有用。
(6)右移运算符(>>)
右移运算是将一个二进制位的操作数按指定移动的位数向右移动,移出位被丢弃,对于左边移出的空位,如果是正数,则一律补0,如果是负数,则可能补0,也可能补0,这由不同的机器决定。
这个运算符可以用来获取一个16位数据的高8位,比如:要获取0x1111的高8位,0xcc11>>8,便可得到高8位0xcc。
到这里,今天的内容就结束了。
如果有写的不合适的地方,还请大家多多指教。如果你有兴趣,也可以一起互相学习,共同进步。 (微信号 :c18093458455)
文章评论(0条评论)
登录后参与讨论