1.位段解释:
因为STM32是32位处理器,所以一般在存取数据时都规定以32位为内存地址进行操作。存储器中有两段地址比较特殊,它允许进行按位操作,称作位段。
分别是:
SRAM的前1MB内存,起始地址0x2000 0000;
外设寄存器的前1MB内存,起始地址0x4000 0000;
2.位段别名区:
按位进行操作没有按照32位内存进行操作快,所以对于位段,将其映射到另一段地址上,将原来位段上的1bit映射为32bit(1bit膨胀为32bit,方便操作),这一段地址叫做位段别名区。
对位段别名区进行操作等同于操作对应位段上一个位的数据。虽然位段别名区有32位,但是只有最低位有效。
位段起始地址对应的位段起始地址:
0x2000 0000 --- 0x2200 0000
0x4000 0000 --- 0x4200 0000
由映射关系可知:
1MB = 1M * 8 bit = 8 Mbit,
所以位段别名区的内存大小为:8 M * 4B = 32MB (将一个bit膨胀为32bit即4B)。
所以位段别名区的地址范围为:
0x2200 0000 --- 0x221F FFFF
0x4200 0000 --- 0x421F FFFF
(可以验算一下,
所占内存 = (0x221F FFFF - 0x2200 0000)B
= 0x1F FFFF B
= 32MB
)
3.对于十六进制地址数据的理解:
地址数据+1等于加了一个字节Byte。
4.位段到位段别名区的地址映射换算:
由以上定义可得:
位段别名区地址 = 位段别名区起始地址 + 位段别名区地址偏移(与位段起始地址的差)。
位段别名区地址偏移 = 位段地址偏移 * 8 * 4 + 该位在该字节中的位置偏移(是第几位)* 4;
5.通用映射代码:
#define A(addr,n) ( ( addr&0xf000 0000 ) + 0x2000 0000 + ( (addr&0xf ffff) << 5 ) + (n << 2) )
注:计算出位段地址为addr,第n位的位的位段别名区地址,<< 5相当于* 32,<< 2相当于* 4;
#define BA(addr,n) ( * ( volatie unsigned int * )A(addr,n) )
注:调用A(addr,n)得到位段别名区地址,强制类型转换成int指针型变量,volatile关键字防止优化,再将该地址的值用BA(addr,n)表示。
BA(addr,n) = 1就可以将该位置1;
可以再度封装:
eg: #define PFout(n) BA(GPIOF_ODR,n)
注:GPIOF_ODR也是一个宏定义,是该寄存器的地址(0x4002 1414)。
参考视频:https://www.bilibili.com/video/BV1BT4y1Q716?share_source=copy_web