本文共 2610 字,大约阅读时间需要 8 分钟。
今天,我想分享一些关于位操作符的知识点,这些对嵌入式开发和计算机基础很有用。位操作是计算机科学中非常重要的基础知识,尤其是在处理硬件接口和底层驱动时,常常需要用到这些高效的操作方式。
位与操作符是一个非常强大的工具,用于按位进行逻辑与操作。& 是位与符号,两个 && 则表示逻辑与操作。例如,两个数 0xAA 和 0xF0 的位与结果是 0xA0。而逻辑与则不一样,0xAA && 0xF0 的结果是 1(因为逻辑与只关心两者是否为真,如果至少有一个为假,结果为假)。
从真值表可以看出:
这种特性使得位与操作非常适合用于清零特定的位或者保留特定位的值。
位或操作符就是它名字说的那样,用于按位或操作。| 是位或符号,两个 || 就表示逻辑或操作。例如,1|0 的结果是 1,0|1 的结果是 1,而 0|0 的结果是 0。
位或操作的特点是,只要有至少一个位为 1,结果位就会为 1。如果你希望某一位变成 1,而其他位保持不变,位或操作就是很好的选择。
位取反是一个非常有用的操作符,它可以将二进制数中的每一位取反(1变成0,0变成1)。在 C 语言中,~ 是按位取反的符号,而 ! 是逻辑取反符号(如果数不为零,则结果为非零,否则为零)。这一点需要特别注意,避免在编程中混淆这两个操作符的含义。
按位取反对数位数的影响非常明显,例如,0xAAAAAAAA 的按位取反结果就是 0x55555555。
位异或操作符就是 ^,它的结果是两个对应位是否相同。如果相同,结果位为 0;不同,结果位为 1。例如,1 ^ 1 的结果是 0,1 ^ 0 的结果是 1。
这些操作符在各种场景下都有不同的应用,下面我们将进一步探讨如何使用这些操作符来操作寄存器。
在嵌入式开发中,寄存器操作是一项非常重要的任务。寄存器通常用来控制外设,例如 GPIO 控制器、定时器等。寄存器操作的特点是对特定位进行操作,而不影响其他位。
ARM 架构中,CPU 与外设寄存器之间是通过 Memory-Mapped IO 统一的,这意味着读写寄存器就是在读写内存。因此,操作寄存器实际上就是在操作硬件。
要清零某个寄存器中的特定位而不影响其他位,可以构造一个掩码,然后与寄存器的当前值进行位与操作。例如,假设寄存器值是 0xAAAAAAAA,我们希望清零 bit8 ~ bit15,可以构造掩码 0xFFFF00FF,然后进行位与操作。
类似地,要将某些特定位置为 1,可以构造一个掩码,然后与寄存器的当前值进行位或操作。例如,如果寄存器中 bit3 ~ bit7 为 0,我们希望它们变为 1,可以写一个掩码 0x1F << 3,然后进行位或操作。
要取反某些特定位,可以使用位异或操作符 ^。例如,如果我们希望位8 ~ bit15 取反,只需要计算 0xFF << 8,然后用 ^ 运算符进行操作。
在嵌入式开发中,经常需要构建特定的二进制数来进行寄存器操作。位运算提供了强大的工具,例如移位和取反,可以帮助我们轻松构建所需的数。
将特定的二进制位构造在一起并进行移位,可以轻松得到对应的数。例如,要构造一个只有 bit3 ~ bit7 为 1,其余位为 0 的数,可以使用 (0x1F << 3) 的方式。
对于那些特定的位缺少连续 1 的情况,可以通过构造位反数再取反来实现。例如,我们需要构造一个 bit4 ~ bit10 为 0,其余位为 1 的数。我们可以先构造 bit4 ~ bit10 为 1 的数,然后对其进行按位取反。
让我来回顾一下位运算的应用场景:
想要构建特定二进制数,可以结合移位和取反操作。
在 C 语言中,可以通过宏定义来封装这些位运算,方便重复使用。例如,定义一些宏辅助函数来完成将特定位设为 1、清零、取反等操作。
#define SET_NTH_BIT(x, n) (x | ((1U) << (n - 1)))#define CLEAR_NTH_BIT(x, n) (x & ~((1U) << (n - 1)))
SET_NTH_BIT(reg, 5)
用于将寄存器的第 5 位置为 1。CLEAR_NTH_BIT(reg, 5)
用于清零寄存器的第 5 位。有时候,我们需要从寄存器中提取某些连续的位。例如,给定寄存器值 0x00001000,想截取 bit 5 ~ bit 7 的值,可以通过以下步骤:
通过合理设计掩码,我们可以轻松截取寄存器中的特定位组合。
以上就是关于位操作符和寄存器操作的全部内容。这些知识点不仅可以帮助你更好地理解内核开发和嵌入式系统的工作原理,还能让你在实际项目中 应用这些技巧。希望这篇文章能为你提供丰富的参考价值!
转载地址:http://ykpuk.baihongyu.com/