首先须要明确下,位段,位带和别名区这三个名词安全
位段:STM32用户参考手册使用的名字app
位带:CortexM3参考手册使用的优化
别名区:地址总线上用来位访问地址区域,spa
因此说,位段和位带是一个意思,是不一样手册的不一样叫法。指针
由上述的名词解释得知,位带功能并非STM32独有的,是CortexM3的功能(CortexM4也有这样的功能)。MCS51有位操做,以一位(bit)为数据对象的操做,MCS51能够简单的将P1口的第2位独立操做:P1.2=0;P1.2=1 ;这样就把P1口的第三个脚(bit2)置0置1。而STM32的位段、位带别名区最重要的就为了实现这样的功能。code
位带是有范围的,并非CortexM3所有地址空间都支持的。在 CM3中,有两个区中实现了位带。其中一个是 SRAM 区的最低 1MB 范围,第二个则是片内外设区的最低 1MB 范围。这两个区中的地址除了能够像普通的 RAM 同样使用外,它们还都有本身的“位带别名区”,位带别名区把每一个比特膨胀成一个 32 位的字。当你经过位带别名区访问这些字时,就能够达到访问原始比特的目的。对象
支持位带操做的两个内存区的范围是:blog
0x2000_0000‐0x200F_FFFF(SRAM 区中最低1MB区域)教程
0x4000_0000‐0x400F_FFFF(片上外设区中的最低 1MB)接口
对 SRAM 位带区的某个比特,记该比特所在字节的地址为A,位序号为 n (0<=n<=7),则它在别名区的地址为:
AliasAddr = 0x22000000 + ((A‐0x20000000)*8+n)*4 =0x22000000 + (A‐0x20000000)*32 + n*4
对于片上外设位带区的某个比特,记该比特所在字节的地址为A,位序号为 n (0<=n<=7),则该比特在别名区的地址为:
AliasAddr = 0x42000000 + ((A‐0x40000000)*8+n)*4 = 0x42000000 + (A‐0x40000000)*32 + n*4
上式中,“*4”表示一个字为 4 个字节,“*8”表示一个字节中有 8 个比特。
把“位带地址+位序号”转换别名地址宏为:
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000 + ((addr &0xFF FFF)<<5) + (bitnum<<2))
把该地址转换成一个指针:
#define MEM_ADDR(addr, bitnum) *((volatile unsigned long *)((addr & 0xF0000000)+0x2000000 + ((addr &0xFF FFF)<<5) + (bitnum<<2)))
其中
addr的取值范围:
0x2000_0000‐0x200F_FFFF
0x4000_0000‐0x400F_FFFF
注意:addr取值要32位对齐
bitnum的取值范围:0-31
解析:
(addr & 0xf0000000) + 0x02000000:
区分SRAM仍是外设,若是是外设,结果为4,再加0x2000000就等于0x4200000,0x42000000就是外设别名位带区。若是是SRAM,结果为2,再加上0x2000000就等于0x22000000,0x22000000就是SRAM别名位带区。
addr & 0x00ffffff:
屏蔽了最高2位,至关于减去0x20000000或者0x40000000。由于位带区的有效范围是1M,即0x100000,这样子就作到了低6位有效。
<< 5:
等价于乘以32
<< 2:
等价于乘以4
特别提醒:
当你使用位带功能时,要访问的变量必须用 volatile 来定义。由于 C 编译器并不知道同一个比特能够有两个地址。因此就要经过 volatile,使得编译器每次都如实地把新数值写入存储器,而再也不会出于优化的考虑。
最容易想到的就是经过 GPIO 的管脚来单独控制每盏 LED 的点亮与熄灭。另外一方面,也对操做串行接口器件提供了很大的方便(典型如 74HC165,CD4094)。位带操做能够把代码缩小, 速度更快,效率更高,更安全。总之位带操做对于硬件 I/O 密集型的底层程序最有用处了
位带操做还能用来化简跳转的判断。
当跳转依据是某个位时,之前必须这样作
一、读取整个寄存器
二、掩蔽不须要的位
三、比较并跳转
使用位带操做后
一、从未带别名区读取状态位
二、比较并跳转
固然,对于写入操做也从4步精简到3步
点击查看本文所在的专辑,STM32F207教程