基于CAN通信的基础学习—C语言位操作
所谓的CAN通信,基本上所有的汽车的整车和别的电子模块的通信方式。
当然本文不是讲解CAN通信的,稍微简单的提一下:所有的通信方式都会有
接收方和发送方,你需要进行通信的话,需要几个基本的原则:
两方都需要同一个波特率,需要相同的(协议)
协议:好像很牛逼的名词,内存能够操作的最小单元是字节,一般协议就是规定
双方能够接受的语言(接收方和发送方),其实就是规定你的报文的每一位对应
的意义,比如你在第一个字节传一个输出电压。。等等
常用的位操作符
因为是做嵌入式开发,后面的数都统一是无符号数
1、位与 & 与 逻辑与&&
位与故名思意就是指一个无符号的数每一位(bit只有两种情况要么1要么0)进行与运算
与运算的特点:
只有两个位都为1的时候,相与才会是真1
只要有一个数不是1的话,那么就是假0
逻辑与&&
就是指一个数(可能它占8位也可能占32位)
一个数只有两种情况:要么是0,要么就不是0
当两个数进行逻辑与的时候,那么只要其中一个数不是0的话,或者两个数都不是0,那么
逻辑与得出的结果就是1
2、位或 | 与 逻辑或 ||
跟位与与逻辑与的区别是一样的,一个是进行每位之间的运算,一个是整体进行或运算
位或的特点:只有两个数等于0的时候才会是0
3、位取反~ 与逻辑取反!
位取反的意思就是当位等于1的时候就是0,当位等于0的时候就是1
逻辑取反!
就比较的有意思了,一个非0的数,取反后就是0
0取反后就是1
4、位异或^
真值表:1^1=0 0^0=0 1^0=1 0^1=1
位异或的特点就是两个位如果相等的话就是0,如果不相等的话就是1
连续异或两个相同的数,得到的值是保持不变的,可以用作密码使用。
5、左移<< 右移>> 箭头朝哪个方向,那么就是向哪里移动。
C语言的移位要取决于数据类型,对于无符号的数来说,怎么移动都可以通过补充0来解决。
对于无符号数,左移时右侧补0(相当于逻辑移位)
对于无符号数,右移时左侧补0(相当于逻辑移位)
对于有符号数,左移时右侧补0(叫算术移位相当于逻辑移位)
(有符号的数需要知道最前面的那一位是符号位,但是左移相当于增大了一倍,所以也是相当于逻辑移位)
对于有符号数,右移时左侧补符号位(叫算术移位,如果是正数补0,负数就是补1)
6、如果操作寄存器
当我想要改变一个寄存器中的某些特定位的时候,我不会直接去给他写。
我会先读出寄存器整体的原来的值,然后在这个基础上修改我想要的特定位,再
将修改值的整体写入寄存器。
在32位处理器的系统中,寄存器的读写一般都是32位一起进行的
这样达成的效果是:在不影响其他位原来值的情况下,我关心的
位的值已经被修改了。
7实战演练
来自朱有鹏的C语言高级专题
特定位清零用&
回顾上节的位与的操作特点:
如果希望将一个寄存器的某些特定位变成0而不影响其他位
可以构造一个合适的1和0组成的数和这个寄存器原来的值进行位与操作,就可以将特定位清零。
举例:假设原来32位寄存器中的值0xAAAAAAAA,我们希望将bit8到
Bit15清零而其他位不变,可以将这个数与
0xffff00ff进行位与即可。
特定位置1 用位或 |
操作手法跟我们位与是一样的,要置1的特定位为1,其他位为0,将这个数原来的数位或即可。
把一个寄存器值的bit4~bit7置1,其他位不变。
4.1、给定一个整型数a,设置a的bit3,保证其他位不变
开始之前把之前的内存
a = a | (1 << 3)
4.2、给定一个整型数a,设置a的bit3~bit7,保持其他位不变
a = a | (0x1f<<3)
4.3、给定一个整型a, 清除bit15,保证其他位不变
要先构建一个相反数。
a = a & (~(1 << 15))
4.4、给定一个整型a, 清除bit15~bit23,和清除bit23到bit29位,保证其他位不变,要清除bit15到23位
a = a & (~(((0x1ff << 15)) | (0x7f << 23)));
—给定一个整形数a,取出a的bit3~bit8。
思路:
第一步:先将这个数bit3~bit8不变,其余位全部清零。
第二步,再将其右移3位得到结果。
第三步,想明白了上面的2步算法,再将其转为C语言实现即可。
a &= (0x3f<<3);
a >>= 3;
----用C语言给一个寄存器的bit7~bit17赋值937(其余位不受影响)。
思路:第一步,先将bit7~bit17全部清零,当然不能影响其他位。
你并不知道bit7~bit`17赋值937
第二步,再将937写入bit7~bit17即可,当然不能影响其他位。
你要赋值的时候哦需要先对原来的数清0
a &= ~(0x7ff<<7);
a |= (937<<7);
技术升级:用宏定义来完成位运算。
#define SET_NTH_BIT(x, n) (x | ((1U)<<(n-1))) //将32位数x的第n位复位,1U是 指1是无符号数(是有好处的,无符 号数左移右移都补0,有符号数的负数左移时补1)
作者:conding123
来源:CSDN
原文:https://blog.csdn.net/dhauwd/article/details/77422369
版权声明:本文为博主原创文章,转载请附上博文链接!