位带区操作
STM32F10x支持位带操作的两个内存区的范围是:
0x2000_0000-0x200F_FFFF(SRAM 区中的最低 1MB)
0x4000_0000-0x400F_FFFF(片上外设区中的最低 1MB)
例如操作GPIOB5->ODR寄存器(GPIOB_ODR寄存器的地址为0x4001080c,则A=0x4001080c)
位带区: 支持位带操作的地址区。
位带别名: 对别名地址的访问最终会变换成对位带区的访问。
AliasAddr= 0x42000000+((A-0x40000000)*8+n)*4 =0x42000000+ (A-0x40000000)*32 + n*4
所操作的位带别名区地址:
AliasAddr=*(volatile uint32_t)0x42000000+((0x4001080c-0x40000000)*8+5)*4
=*(volatile uint32_t)0x42000000+ (0x4001080c-0x40000000)*32 + 5*4
=*(volatile uint32_t)0x42218194
#define PB5 *(volatile uint32_t)0x42000000+((0x4001080c-0x40000000)*8+5)*4
#define PB5 *(volatile uint32_t)0x42000000+ (0x4001080c-0x40000000)*32 + 5*4
#define PB5 *(volatile uint32_t)0x42218194
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
(1)将位带区地址的计算宏定义成“地址+偏移”
(2)再将该地址转换成一个指向该位带别名区的指针
(3)宏定义访问位带别名区地址
用位带区操作的优缺点:
1.优点
相比直接操作寄存器代码更简洁,运行效率更高。避免在多任务,或中断时出现紊乱等。
2.缺点
操作不当(传入地址参数不对),容易出现总线Fault。
volatile关键字的用法
volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,告诉编译器对该变量不做优化,都会直接从变量内存地址中读取数据,从而可以提供对特殊地址的稳定访问。
如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。(简洁的说就是:volatile关键词影响编译器编译的结果,用volatile声明的变量表示该变量随时可能发生变化,与该变量有关的运算,不要进行编译优化,以免出错.