按位操作符用于计算每一位的操作的。这样就能解决各种常见的编程问题。以下资料来自一篇很棒的教程,关于位计算。原文可见,点击此处

【描述】 以下是这篇教程写的运算符的描述和相关语法。更多细节可见原文

【按位与(&)】 按位与用符号"&"表示,常用于两个整型变量之间。按位与(&)是对每一位作运算。规则如下:如果两个输入都为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是串口通信端口,也可能会对通信造成影响。

下面这段代码的意思是:

  1. 读取PORTD,通过按位与(&)清除每一位对应的引脚。
  2. 并通过按位或(|)将新的值赋给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

<File:nextredirectltr.png>返回Arduino语法手册首页

<File:nextredirectltr.png>更多建议,指正,或者文档分享欢迎进入DF创客社区