单片机 - 位运算详解(`&`、`|`、`~`、`^`、`>>`、`<<`)

单片机中的位运算详解(&|~^>><<

位运算是单片机编程(C/C++)中经常使用的技巧,用于高效地操作寄存器、I/O 端口和数据。以下是各位运算符的详细解析,并结合单片机实际应用举例。

1. 按位与(&):用于位清零、检测某个位是否为 1

特点:

  • 两个二进制位都为 1,结果才为 1,否则为 0

单片机应用场景:

  • 用于屏蔽特定位(清零特定位)。
  • 检测某个位是否为 1

示例:

假设 P1 代表某个 I/O 端口,我们想要清除 P1 端口的第 3 位(保留其他位不变)。

c 复制代码
P1 = P1 & 0b11110111; // 清除 P1 端口的第 3 位(从 0 开始编号)

示例:检测某个位是否为 1

c 复制代码
if (P1 & (1 << 3)) {  
    // 第 3 位为 1,执行某些操作
}

2. 按位或(|):用于位设为 1

特点:

  • 只要有一个二进制位为 1,结果就是 1

单片机应用场景:

  • 用于设置某个位为 1(打开某个功能)。

示例:

假设 P2 端口连接了 LED,我们要点亮 LED(假设 LED 连接在 P2 的第 2 位)。

c 复制代码
P2 = P2 | 0b00000100; // 设置 P2 端口的第 2 位为 1

或使用移位操作

c 复制代码
P2 |= (1 << 2);

3. 按位取反(~):对所有位取反

特点:

  • 0 变 1,1 变 0。

单片机应用场景:

  • 用于翻转数据,例如按键检测、反向输出。

示例:

如果 P3 端口是某个设备的控制信号,我们想要翻转它:

c 复制代码
P3 = ~P3; // 让所有位取反

示例:只翻转 P3 端口的第 5 位

c 复制代码
P3 ^= (1 << 5);

4. 按位异或(^):用于翻转某个位

特点:

  • 1 ^ 1 = 0
  • 0 ^ 1 = 1
  • 1 ^ 0 = 1
  • 0 ^ 0 = 0

单片机应用场景:

  • 用于翻转(取反)某一位。

示例:

如果 P4 端口的第 1 位用于指示 LED,我们想要让它每次调用时反转:

c 复制代码
P4 ^= (1 << 1); // 让 P4 端口的第 1 位取反

5. 取反再异或(~^):等价于按位 XNOR(同或)

特点:

  • ~(a ^ b),即两个相同位为 1,不同位为 0

单片机应用场景:

  • 用于比较两位是否相等。

示例:

判断 AB 是否相等(所有位均相同)。

c 复制代码
if (~(A ^ B) == 0xFF) {  
    // A 和 B 完全相同
}

6. 左移运算(<<):用于乘 2 的幂次方

特点:

  • a << n 相当于 a × (2^n)

单片机应用场景:

  • 快速计算 2 的倍数。
  • 控制某个位的移位。

示例:

假设 P5 连接了一个 8 段 LED,我们希望轮流点亮 LED:

c 复制代码
for (int i = 0; i < 8; i++) {
    P5 = 1 << i; // 依次点亮 LED
}

7. 右移运算(>>):用于除 2 的幂次方

特点:

  • a >> n 相当于 a / (2^n)

单片机应用场景:

  • 用于快速除法。
  • 数据解码时提取某几位。

示例:

假设 sensorData 是一个 16 位的传感器数据,我们想提取高 8 位:

c 复制代码
uint8_t highByte = sensorData >> 8;

举例应用:按键消抖

单片机中按键输入可能会因机械抖动导致错误读取,我们可以结合位运算实现按键消抖:

c 复制代码
#define KEY_PIN P3_0  // 假设按键连接 P3.0 端口

void delay() {
    for (volatile int i = 0; i < 5000; i++);  // 简单延时
}

uint8_t readKey() {
    if ((P3 & (1 << 0)) == 0) {  // 检测按键是否按下
        delay();
        if ((P3 & (1 << 0)) == 0) {  // 再次检测,确认消抖
            return 1;  // 按键按下
        }
    }
    return 0;  // 按键未按下
}

总结

运算符 作用 单片机应用
& (按位与) 清零某个位,检测某个位 读取 I/O 端口状态
按位或 设置某个位为 1 控制 LED、使能外设
~ (按位取反) 取反所有位 翻转 I/O 信号
^ (按位异或) 仅翻转某个位 翻转 LED 状态
~^ (XNOR) 比较两数据是否相同 数据校验
<< (左移) 乘 2 的幂 快速计算、移位
>> (右移) 除 2 的幂 提取高位数据

(完)

相关推荐
口袋物联5 小时前
设计模式之工厂模式在 C 语言中的应用(含 Linux 内核实例)
linux·c语言·设计模式·简单工厂模式
Want5957 小时前
C/C++跳动的爱心①
c语言·开发语言·c++
lingggggaaaa7 小时前
免杀对抗——C2远控篇&C&C++&DLL注入&过内存核晶&镂空新增&白加黑链&签名程序劫持
c语言·c++·学习·安全·网络安全·免杀对抗
gfdhy7 小时前
【c++】哈希算法深度解析:实现、核心作用与工业级应用
c语言·开发语言·c++·算法·密码学·哈希算法·哈希
刻BITTER8 小时前
用EXCEL 将单色屏幕的Bitmap 字模数据还原回图形
单片机·嵌入式硬件·excel·arduino
我不会插花弄玉8 小时前
vs2022调试基础篇【由浅入深-C语言】
c语言
福尔摩斯张9 小时前
《C 语言指针从入门到精通:全面笔记 + 实战习题深度解析》(超详细)
linux·运维·服务器·c语言·开发语言·c++·算法
fashion 道格9 小时前
数据结构实战:深入理解队列的链式结构与实现
c语言·数据结构
铁手飞鹰10 小时前
二叉树(C语言,手撕)
c语言·数据结构·算法·二叉树·深度优先·广度优先
撬动未来的支点10 小时前
【嵌入式】MCU和MPU的区别
单片机·嵌入式硬件