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