位带区域
定义
STM32F407 的 位带机制(Bit-Band)是 Cortex-M4 内核提供的一种硬件特性,允许通过单个原子操作直接读写内存或外设寄存器中的某一位,而无需传统的“读-改-写”过程。
(1) 位带区(Bit-Band Region)
- 定义:支持位带操作的原始内存或外设区域。
- 范围:
- 外设寄存器区:
0x40000000~0x40100000
(1MB) - SRAM 区:
0x20000000~0x20100000
(1MB)
- 外设寄存器区:
(2) 位带别名区(Bit-Band Alias Region)
- 定义:通过别名地址访问位带区中单个位的映射区域。
- 范围:
- 外设别名区:
0x42000000~0x43FFFFFF
(32MB) - SRAM 别名区:
0x22000000~0x23FFFFFF
(32MB)
- 外设别名区:
- 映射规则:
位带区中的 1 位 ↔ 别名区中的 1 个 32 位字(即 4 字节)。
(3) 地址转换公式
要操作位带区中某地址的某一位,需先计算对应的别名地址:
别名地址=别名基地址+(字节偏移×32)+(位号×4)别名地址=别名基地址+(字节偏移×32)+(位号×32 / 8)
- 别名基地址:
- 外设别名区:
0x42000000
- SRAM 别名区:
0x22000000
- 外设别名区:
- 字节偏移:目标地址与位带区起始地址的偏移(单位:字节)。
- 位号:目标位的序号(0~7)。
示例:操作 GPIO 引脚(外设寄存器)
假设需要控制 GPIOA->ODR
寄存器的第 5 位(PA5 引脚):
-
目标地址:
GPIOA->ODR
的地址为0x40020014
。 -
计算别名地址:
别名地址 = 0x42000000 + (0x40020014 - 0x40000000) * 32 + 5 * 4 = 0x42000000 + 0x20014 * 32 + 20 = 0x42000000 + 0x400280 + 0x14 = 0x42400294
代码如下:
// 定义位带别名地址
#define PA5_OUT (*((volatile uint32_t *)0x42400294))
PA5_OUT = 1; // 将 PA5 置高电平
PA5_OUT = 0; // 将 PA5 置低电平
通用公式如下:
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
注意:位移运算比算术运算效率更高。
意义
STM32F407基于32位的ARM Cortex-M4内核,其数据总线宽度为32位,所有内存访问操作均以32个比特位(4字节)为单位进行。因此,位带别名区的每个比特位映射到32位地址空间,保证了内存对齐和原子性操作的高效性。
位带机制的优势
- 原子操作:单指令完成位操作,避免中断打断风险。
- 代码简洁:无需手动进行位运算(如
|=
、&=
)。 - 执行高效:减少指令周期,提升实时性。
常见问题
对于STM32F407中的位带机制,为什么一个比特位膨胀为32个比特位呢?
根本原因是,STM32F407使用的是32位的Cortex-M4内核,数据总线是32位的,因此每次访问内存或外设时,处理器通常以32位为单位进行一个独立的不可分割的操作,提高了性能和保证了原子性操作。
如何使用(重点)
作为使用者,仅需要熟练掌握如何通过位带机制操作写入别名地址的值以及读取别名地址的值。而与位带相关的宏定义一般定义在头文件sys.h
中
例如:
// 将 PA5 置 1
*(volatile uint32_t*)0x42400294 = 1; // 实际写入 0x00000001
// 读取 PA5 的状态
uint32_t state = *(volatile uint32_t*)0x42400294; // state 的 bit0 即 PA5 的值