文章目录

  • 1 位操作
    • 1.1 按位与
    • 1.2 按位或
    • 1.3 按位异或
    • 1.4 取反
    • 1.5 左移
    • 1.6 右移
  • 2 单片机中常用操作
    • 2.1 不改变其他位时,对某几个位设定值
    • 2.2 移位操作提高代码可读性
    • 2.3 取反操作使用技巧

1 位操作

运算符 含义
& 按位与
按位或
^ 按位异或
~ 取反
<< 左移
>> 右移

c 语言中存在以上 6 个位操作运算符,且它们只能用于整形操作数。

总结:对于原二进制数来说,&0是屏蔽,&1是不变。

总结:对于原二进制数来说,|0是不变,|1是置1。

总结:对于原二进制数来说,^0是不变,^1是反转。


1.1 按位与

按位与的定义是:同一二进制位上的数字都是1的话,& 的结果为1,否则为0。

运算 结果
0 & 0 0
0 & 1 0
1 & 0 0
1 & 1 1

根据这个特性,& 操作常常用来屏蔽特定的二进制位。

例如:0000 1111 & 0000 0011 = 0000 0011

与运算 0 0 0 0 1 1 1 1
& 0 0 0 0 0 0 1 1
结果 0 0 0 0 0 0 1 1

可以看见,1111的前两位被屏蔽成为0了。

所以如果想清空数据,只需要将原二进制数与上 &0 就可以了。0的位数对应原二进制数的位数,对各位进行屏蔽,全部置0。

相对的,&可以利用0来屏蔽,也可以用1来读取。

例如: 一个二进制数 1101 1001,我只想要它的后四位,怎么办呢?

只需要进行如下操作:1101 1001 & 0000 1111即可。

与运算 1 1 0 1 1 0 0 1
& 0 0 0 0 1 1 1 1
结果 0 0 0 0 1 0 0 1

其实该方法是屏蔽和读取的结合,&0保证消除无用位,&1保证有用数据的完整性。

总结:对于原二进制数来说,&0是屏蔽,&1是不变。


1.2 按位或

定义:只要参与运算的双方其中有一个是1,结果就是1.同0才为0。

运算 结果
0 | 0 0
0 | 1 1
1 | 0 1
1 | 1 1

主要用作将某些特定位置1。

例如:1010 0000 | 0000 1111 = 1010 1111。

或运算 1 0 1 0 0 0 0 0
0 0 0 0 1 1 1 1
结果 1 0 1 0 1 1 1 1

总结:对于原二进制数来说,|0是不变,|1是置1。


1.3 按位异或

只要参与运算的双方互异,结果就为1,否则为0。

运算 结果
0 ^ 0 0
0 ^ 1 1
1 ^ 0 1
1 ^ 1 0

可以通过上面的定义看到,一个数^1 的话就会0变成1,1变成0,而^0则不对原数进行改变。所以根据此特性可以对特定位进行0 1 反转。

例如: 1100 1100 ^ 0000 1100 = 1100 0000。

异或运算 1 1 0 0 1 1 0 0
^ 0 0 0 0 1 1 0 0
结果 1 1 0 0 0 0 0 0

同样的,如果对一个数进行^0,代表保留原值。

总结:对于原二进制数来说,^0是不变,^1是反转。


1.4 取反

对一个二进制数进行取反。1变0,0变1。

唯一需要注意的一点是,~的优先级是逻辑运算符中最高的,必须优先计算。


1.5 左移

左移与右移比较类似,是将目标二进制数字向左/右移动相应的位数。

左移补0:1111 1111 << 1 == 1111 1110,换算十进制的话是原来数值的2倍。

左移 1 1 1 1 1 1 1 1
<< 1
结果 1 1 1 1 1 1 1 0

1.6 右移

右移看情况:负数补1,正数补0。需要看符号位。同样,换算为十进制数值变为原来的1/2.

右移 1 1 1 1 1 1 1 1
>> 1
结果 0 1 1 1 1 1 1 1

总结:左乘右除。


2 单片机中常用操作

2.1 不改变其他位时,对某几个位设定值

比如要改变 GPIOA 的状态,可以先对寄存器的值进行 & 清零操作

GPIOA -> CRL &= 0XFFFFFF0F;      // 将第 4-7 位清 0

然后再与需要设置的值进行 或运算

GPIOA -> CRL |= 0X00000040;      // 设置相应位的值,且不改变其他位的值

2.2 移位操作提高代码可读性

以固件库的 GPIO 初始化的函数里一行代码为例

GPIOx -> BSRR = (((uint32_t)0x01) << pinpos);

这个操作就是将 BSRR 寄存器的第 pinpos 位设置为 1。
为什么要通过左移而不是直接设定呢?其实,这是为了提高代码的可读性以及可重用性。这行代码可以直观明了的知道,是将第 pinpos 位设置为 1。

如果写成

GPIOx -> BSRR = 0x0030;

这样的代码就不容易看出,也不好重用了。

类似的代码还有:

GPIOA -> ORT |= 1<<5;      // PA.5 输出高,不改变其他位

这样我们一目了然,5 告诉我们是第 5 位也就是第 6 个端口,1 告诉我们是设置成了 1。

2.3 取反操作使用技巧

SR 寄存器的每一位都代表一个状态,某个时刻我们希望去设置某一位的值为 0,同时其他位都保留位 1,简单的作法是直接给寄存器设置一个值:

TIMx -> SR = 0xFFF7;

这样做法可读性交较差。

看看库函数中代码是如何使用的:

TIMx -> SR = (uint16_t)~TIM_FLAG;

而 TIM_FLAG 是通过宏定义完成的值:

#define TIM_FLAG_Update      ((uint16_t)0x0001)
#define TIM_FLAG_CC1        ((uint16_t)0x0002)

看这个就容易明白,可以直接从宏定义重看出 TIM_FLAG_Update 就是设置的第 0 位了,可读性较强。


Ref: C语言中的逻辑运算符:按位与,按位或,按位异或,取反,左右移位
Ref: STM32 不完全手册 - 立创开源

【STM32】位操作、按位与、按位或、按位异或、取反、左移、右移等基础 C 语言知识补充相关推荐

  1. 位运算符:按位与(),按位或(|),按位异或(^),取反(~)左移()和右移()

    数据在内存中是以二进制的形式存放的,计算机存储数据的最小单位是位(bit),一个二进制位可以表示两种状态(0和1),一个字节通常由8位二进制位组成.C语言支持按位运算,按位运算也就是对字节或者字中的实 ...

  2. 基础C语言知识串串香7☞位操作

    文章参考微信公众号[嵌入式软件学习圈] 二.位操作 2.1 ~(0u)是全1: 2.2 位与& 位或 | 位取反~ 位异或^ 2.3.位与.位或.位异或的特点总结: 位与:(任何数,其实就是1 ...

  3. C语言按位与 按位或 按位异或 按位取反

    与运算:& 两者都为1为1,否则为0 1&1=1,  1&0=0,  0&1=0,  0&0=0 或运算:| 两者都为0为0,否则为1 1|1 = 1,  1| ...

  4. C语言按位与 按位或 按位异或 按位取反(二)

    位运算是指按二进制进行的运算.在系统软件中,常常需要处理二进制位的问题.C语言提供了6个位操作运算符.这些运算符只能用于整型操作数,即只能用于带符号或无符号的char,short,int与long类型 ...

  5. 位与()、位或(|)、异或(^) 、左移<<、右移>>、原码、反码、补码的简单应用

    一.位与(&).位或(|).异或(^) 1.位与运算(&):两位同时为1,结果才为1,否则为0 参加运算的两个数据,按二进制位进行"&"运算. 运算规则:0 ...

  6. C语言按位与 按位或 按位异或 按位取反 (一)

    与运算:& 两者都为1为1,否则为0 1&1=1,  1&0=0,  0&1=0,  0&0=0 或运算:| 两者都为0为0,否则为1 1|1 = 1,  1| ...

  7. 位操作-置0,置1,取反以及获取某位是0还是1

    u32 a=0x00AA; a |=(1<<5) ;//第5位置1 a &=~(1<<5) ;//第5位置0 a ^=(1<<5) ;//第5位取反 if( ...

  8. 位运算(按位与、按位或、异或、取反)以及原码、反码、补码

    参考:运算符的计算(按位与 按位或 异或 取反) 作者:一只青木呀 发布时间: 2020-07-23 18:13:55 网址:https://blog.csdn.net/weixin_45309916 ...

  9. 位操作符详解(移位操作符(左移/右移)、按位与‘’操作符、按位或‘|’操作符、按位异或‘^’操作符)

    位操作是程序设计中对位模式按位或二进制数的一元和二元操作: 在许多微处理器上,位运算与加减运算速度大致相同,但位运算的速度远快于乘法运算: 位操作符的使用,可以使我们在处理一些问题上方便许多. 移位操 ...

最新文章

  1. linux gcc安装
  2. 干货丨卷积神经网络工作原理的直观解释
  3. K.O. -------- Eclipse中Maven的报错处理
  4. 3.10以上charles版本抓取Https数据包
  5. 【企业管理】围绕价值创造开展人力资源管理
  6. Oracle goldengate 11g错误汇总
  7. 数据结构与算法之“之”字型打印矩阵和矩阵中找数
  8. 带你见识世界的5部纪录片(免费领取)
  9. 【debug】使用lambda在循环中传参时,参数总为同一个值
  10. 【华为云技术分享】云小课 | SAP容灾一点通
  11. centos7 安装VNC Server
  12. 单行文本溢出省略以及多行文本溢出省略css实现方式
  13. 帆软客户画像分析与客户价值模型
  14. 单片机开发之嵌入式基础
  15. 《云计算技术与应用基础》课程标准
  16. Essential Matrix 的求解算法--Nister 五点算法以及原理
  17. 写一篇最好懂的HTTPS讲解
  18. Zabbix 4.2 支持 Prometheus 数据收集
  19. Wayland 下使用腾讯会议
  20. 傻瓜式解决pycrypto安装错误

热门文章

  1. crossdomain 可用
  2. 类成员函数作为函数参数/回调函数 出现error C3867
  3. SpringMVC访问静态资源的三种方式
  4. PyQt 5布局管理
  5. 怎么添加项目到SVN上面
  6. Android之Bmob移动后端云服务器
  7. 《实时控制软件开发》学生四次作业成绩总排名
  8. 天津政府应急系统之GIS一张图(arcgis api for flex)讲解(四)地图导航控件模块...
  9. mapreduce 算法
  10. Ubuntu 9.04安设教程(傻瓜版)