作者:嘉兴布奇乐乐园 | 来源:互联网 | 2023-08-10 19:04
最近思来想去,觉得需要技术沉淀,于是我注册了个微信公众号(airX嵌入式),这也是为我后续创业公司做准备,一来能分享记录我的开发项目,以及开源一切设计;二来能结识更多的同道中人!有机会可以合作创业!
微信扫码关注我!(airX嵌入式)
![](https://img8.php1.cn/3cdc5/186f6/ae9/e1a9073b09b33030.jpeg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzIyNTIwMjE1,size_16,color_FFFFFF,t_70)
在C项目中,我们常常会遇到设置某个参数中的n位数值或者读取某个参数的n位数值,如果每次都口算出整个参数的值再使用与或算法那真的费时间,弄不好算错了那就更麻烦了!
举个例子:假设寄存器A为32Bit长度寄存器,请将27位的值置位0?
如果你傻傻的有下面这个做法,那建议你把这篇文章看完,对你肯定有帮助。
做法:根据与或运算法则,算出当27位为0,其他位为1的32bit的值为
0xF7FFFFFF;
然后A &=0xF7FFFFFF;
为了杜绝上面的麻烦和错误的风险!
下面我列举几个常见的操作,也是本人写代码的操作:
声明:以下说到的寄存器当然是可以读取写入的寄存器
写操作:
1、把寄存器/变量的第n位清零,不改变其他位的数值
void a;
a= 0x12345678;
a &&#61;~(1<<12); //第12bit置0&#xff0c;其他不变&#xff1b;
同理&#xff1a;a &&#61; ~(1<<27); //第27bit置0&#xff0c;其他不变&#xff1b;
公式&#xff1a;a &&#61;~(1<
2、把寄存器/变量的第n位起的连续m位清零&#xff0c;不改变其他位的数值
void a&#xff1b;
a &#61; 0x12345678&#xff1b;
a &&#61; ~(3<<1); //第1位起的连续2位清零
a &&#61; ~(7<<2); //第2位起的连续3位清零
公式 a &&#61; ~((2^m-1)< 2^m-1表示的是m位都为1的二进制的十进制数值&#xff0c;比如3表示二进制0b00000011&#xff0c;表示连续2位&#xff1b;7表示二级制0b00000111&#xff0c;表示连续3位&#xff1b;
3、把寄存器/变量的第n位置1&#xff0c;不改变其他位的数值
void a&#xff1b;
a &#61; 0x12345678&#xff1b;
a |&#61; (3<<1); //第1位起的连续2位置1
a |&#61; (7<<2); //第2位起的连续3位置1
公式&#xff1a;a |&#61;(1<
4、把寄存器/变量的第n位起的连续m位置1&#xff0c;不改变其他位的数值
void a&#xff1b;
a &#61; 0x12345678&#xff1b;
a |&#61; (3<<1); //第1位起的连续2位置1
a |&#61; (7<<2); //第2位起的连续3位置1
公式 a |&#61; ((2^m-1)< 2^m-1表示的是m位都为1的二进制的十进制数值&#xff0c;比如3表示二进制0b00000011&#xff0c;表示连续2位&#xff1b;7表示二级制0b00000111&#xff0c;表示连续3位&#xff1b;
5、对寄存器/变量的第n位取反
void a&#xff1b;
a &#61; 0x12345678&#xff1b;
a ^&#61; (1<<1); //第1位取反
a ^&#61; (1<<2); //第2位取反
公式&#xff1a;a ^&#61; (1<
读操作&#xff1a;
1、读寄存器/变量的第n位
void a&#xff0c;result&#xff1b;
a &#61; 0x12345678&#xff1b;
result&#61;a& (1<<2); //读第2位
result&#61;a& (1<<3); //读低3位
公式&#xff1a;result&#61;a& (1<
2、读寄存器/变量的第n位起的连续m位
void a&#xff0c;result&#xff1b;
a &#61; 0x12345678&#xff1b;
result&#61;a& (3<<2); //读第2位开始的连续2位数据
result&#61;a& (3<<27); //读第27位开始的连续2位数据
公式result&#61;a& ((2^m-1)< 2^m-1表示的是m位都为1的二进制的十进制数值&#xff0c;比如3表示二进制0b00000011&#xff0c;表示连续2位&#xff1b;7表示二级制0b00000111&#xff0c;表示连续3位&#xff1b;
像这种操作&#xff0c;判断时可以完全脱离位置的计算&#xff0c;只需看变量名称就可操作&#xff01;
下面这些是别人厂家的库函数&#xff1a;也是如此定义
![图片](https://img8.php1.cn/3cdc5/186f6/ae9/aa8e3a5ffe946e3f.png)
![图片](https://img8.php1.cn/3cdc5/186f6/ae9/af27d41303f7d1bf.png)
清除的操作&#xff1a;
![图片](https://img8.php1.cn/3cdc5/186f6/ae9/37579e1807380f67.png)
清除置位都有的函数&#xff0c;只需传入上面宏定义的参数即可操作&#xff1b;
![图片](https://img8.php1.cn/3cdc5/186f6/ae9/e0b96ba29d483a08.png)
下面是我的一个断路器项目&#xff0c;其中因为要记录各种故障原因&#xff0c;因此需要很多的标志位&#xff01;
1、我的第一步操作就是使用位移操作宏定义故障原因&#xff0c;如下1&#xff0c;以及一个缓存故障原因的缓存变量&#xff0c;如图2&#xff1b;
![图片](https://img8.php1.cn/3cdc5/186f6/ae9/2dc2a8e11110f0bb.png)
图1
图2
2、构建获取相应故障状态的函数&#xff0c;如下操作&#xff1a;
![](https://img8.php1.cn/3cdc5/186f6/ae9/fde95c3a78048215.png)
![](https://img8.php1.cn/3cdc5/186f6/ae9/eeb7c35b0b49266c.png)
3、构建清除相应故障状态的函数&#xff0c;如下操作&#xff1a;
![图片](https://img8.php1.cn/3cdc5/186f6/ae9/2b337c1c640225ee.png)
4、构建设置相应故障状态的函数&#xff0c;如下操作&#xff1a;
![图片](https://img8.php1.cn/3cdc5/186f6/ae9/30dd0b53bf14c312.png)
最后只需调用&#xff0c;传入相应的故障宏定义即可&#xff01;这样做的话&#xff0c;直接读函数名就可以知道该函数的作用&#xff01;避免当枚举太多&#xff0c;导致混乱&#xff01;
微信扫码关注我&#xff01;&#xff08;airX嵌入式&#xff09;
![](https://img8.php1.cn/3cdc5/186f6/ae9/e1a9073b09b33030.jpeg?x-oss-process&#61;image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzIyNTIwMjE1,size_16,color_FFFFFF,t_70)