1、按位与(AND)操作
按位与操作用于清除特定位。只有在两个操作数的对应位都是1时,结果位才为1,否则为0。
示例:
#define LED_PIN 5
// 清除寄存器中的LED_PIN位(例如,在GPIOA端口)
GPIOA->ODR &= ~(1 << LED_PIN);
在这个示例中,假设“LED_IN”是5。“1 << LED_PIN”
会生成一个只有第5位为1,其它位为0的数值(二进制:000100000)。“~”操作符对其取反,结果是所有位都是1,只有第5位是0(二进制:111011111)。使用按位与操作“&=”将第5位置0,其它位保持不变。
2、按位或(OR)操作
按位或操作用于设置特定位。只要两个操作数的对应位中有一个是1,结果位就为1。
示例:
#define LED_PIN 5
// 设置寄存器中的LED_PIN位(例如,在GPIOA端口)
GPIOA->ODR |= (1 << LED_PIN);
在这个示例中,1 << LED_PIN
会生成一个只有第5位为1,其它位为0的数值(二进制:000100000)。使用按位或操作“|=”
将第5位置1,而不影响其它位。
3、左移(Shift Left)操作
左移操作用于将寄存器中的位左移特定数量的位,右边填0。左移操作相当于乘以2的n次方(n是左移的位数)。
示例:
#define LED_PIN 5
// 将寄存器值左移5位(例如,将1左移5位)
uint32_t result = 1 << LED_PIN;
在这个示例中,1 << LED_PIN
会将1左移5位,结果是二进制的000100000(即十进制的32)。
4、综合示例
以下是一个综合的示例,展示如何使用这些操作来配置STM32的GPIO端口:
假设我们要配置GPIOA的第5位为输出模式,并设置该位。
// 配置GPIOA的模式寄存器,将第5位配置为输出模式
#define LED_PIN 5
#define GPIOA_BASE 0x40020000
#define GPIOA_MODER (*((volatile uint32_t *)(GPIOA_BASE + 0x00)))
#define GPIOA_ODR (*((volatile uint32_t *)(GPIOA_BASE + 0x14)))
// 1. 清除第5位的两位(MODER寄存器控制每个引脚的模式,每个引脚占2位)
GPIOA_MODER &= ~(0x3 << (LED_PIN * 2));
// 2. 设置第5位的两位为01(表示输出模式)
GPIOA_MODER |= (0x1 << (LED_PIN * 2));
// 3. 设置ODR寄存器的第5位为1(点亮LED)
GPIOA_ODR |= (1 << LED_PIN);
// 4. 清除ODR寄存器的第5位(熄灭LED)
GPIOA_ODR &= ~(1 << LED_PIN);
在这个例子中:
GPIOA_MODER &= ~(0x3 << (LED_PIN * 2))
:清除MODER寄存器中与LED_PIN相关的两位。GPIOA_MODER |= (0x1 << (LED_PIN * 2))
:设置MODER寄存器中与LED_PIN相关的两位为01,即配置为输出模式。GPIOA_ODR |= (1 << LED_PIN)
:设置ODR寄存器中的第5位,点亮LED。GPIOA_ODR &= ~(1 << LED_PIN)
:清除ODR寄存器中的第5位,熄灭LED。
这些操作在嵌入式编程中非常重要,可以精确控制微控制器的硬件资源。通过理解并掌握这些位操作,可以更高效地进行寄存器配置和操作。