按位操作符用于计算每一位的操作的。这样就能解决各种常见的编程问题。以下资料来自一篇很棒的教程,关于位计算。原文可见,点击此处。
【描述】
以下是这篇教程写的运算符的描述和相关语法。更多细节可见原文。
【按位与(&)】
按位与用符号**"&"**表示,常用于两个整型变量之间。**按位与(&)**是对每一位作运算。规则如下:如果两个输入都为1,结果为1,否则输出为0。另一种表达方式是:
0 0 1 1 运算数1
0 1 0 1 运算数2
----------
0 0 0 1 (运算数1 & 运算数2) - 返回值
在Arduino中,int型是16位的数。所以,两个int型相与的话,是16位数同时作按位与运算。可如下表达:
int a = 92; // 二进制: 0000000001011100
int b = 101; // 二进制: 0000000001100101
int c = a & b; // 结果: 0000000001000100, 或者 68(十进制).
16位数a和b作按位与运算,其计算结果将存储在C中,并且结果可用二进制01000100,或者十进制68表示。
**按位与(&)**最常用的一种用法是,从某个整型数中取某一位,也称之为掩码屏蔽。
【按位或(|)】
按位或用符号**"|"表示。类似于按位与(&)**,**按位或(|)**也是对每一位进行运算。区别在于,**按位或(|)**是,两个输入值,只有其中一个为1,那么输出为1,否则为0。换句话说:
0 0 1 1 运算数1
0 1 0 1 运算数2
----------
0 1 1 1 (运算数1 | 运算数2) - 返回值
16进制也是同样原理:
int a = 92; //二进制: 0000000001011100
int b = 101; //二进制: 0000000001100101
int c = a | b; //结果: 0000000001111101, 或者125(十进制)。
【示例】
**按位与(&)和按位或(|)**在程序中常用作端口的"读取--修改--写入"。芯片中,一个端口通常是8位,用来表示对应引脚的状态。端口数值的写入可以同时控制所有引脚。
PORTD是内置常数,用来控制0,1,2,3,4,5,6,7数字引脚的状态。如果某一位都设置为1,那么所对应的引脚被设置为HIGH。(前提条件是,需要先用pinMode()指令将引脚设置为输出状态)
所以,如果我们代码写入 PORTD = B00110001; 意思是,我们将引脚2,3,7设置为HIGH。会带来一个问题,修改的同时,引脚0和1的状态可能也发生了变化。引脚0和1是串口通信端口,也可能会对通信造成影响。
下面这段代码的意思是:
- 读取PORTD,通过**按位与(&)**清除每一位对应的引脚。
- 并通过**按位或(|)**将新的值赋给PORTD。
int i; // 该变量用来计数
int j;
void setup(){
DDRD = DDRD | B11111100; //设置2~7号引脚的方向,并保持0和1不变(xx | 00 == xx)。
//和pinMode(pin,OUTPUT)设置2~7脚为输出效果相同
Serial.begin(9600);
}
void loop(){
for (i=0; i<64; i++){
PORTD = PORTD & B00000011; // 清除2~7位,保持引脚0和1不变。(xx & 11 == xx)
j = (i << 2); // 将变量左移为·2~7脚,避免0、1脚
PORTD = PORTD | j; // 将新状态和原端口状态结合以控制LED脚
Serial.println(PORTD, BIN); // 输出掩盖以便调试
delay(100);
}
}
【按位异或(^)】
C++有个非常不一样的操作符,叫做按位异或,用符号"^"表示。这个操作符和按位与(&),**按位或(|)**用法类似。区别在于,当两个值都为1,其结果为0,否则为0。用法如下:
0 0 1 1 运算数1
0 1 0 1 运算数2
----------
0 1 1 0 (运算数1 ^ 运算数2) - 返回值
还可以这样理解按位异或(^),如果输入位不同,输出结果为1。相反,如果相同,输出结果为0。
有个简单的例子可以看下:
int x = 12; //二进制: 1100
int y = 10; //二进制: 1010
int z = x ^ y; //二进制: 0110,或者 6(十进制)
按位异或(^)在位操作中常用于触发器(比如,从0变为1,或者1变为0)。比如,在按位异或操作式中,如果1是个掩码位,那么就翻转。如果是0,则不翻转。下面这段代码就通过引脚5来实现该功能:
//使引脚5在0和1直接翻转
// 按位异或使用样例代码
void setup(){
DDRD = DDRD | B00100000; //设置引脚5为输出状态
Serial.begin(9600);
}
void loop(){
PORTD = PORTD ^ B00100000; //翻转引脚5的状态,其他引脚保持不变
delay(100);
}
翻译自:Arduino Language Reference
更多建议,指正,或者文档分享欢迎进入DF创客社区