一、位带操作的原理
51单片机可以直接对某一位IO进行读写操作,而STM32则通过位带操作来控制一个单独的IO口。
概念
- 位带区:支持位带操作的地址区。
- 位带别名区:对别名地址的访问最终作用到位带区的访问上。位带别名区对位带区的访问有个地址映射过程。
目的
对位带区的比特位进行独立的读写操作,即单独操作一个位 ,它是通过对位带别名区的操作来实现。
具体过程:
对位带别名区进行读写访问,位带别名区通过地址映射关系映射到相应的位带区,对位带区进行原始比特的读写操作。
地址映射
对位带别名区进行读且操作 ---------------------->对位带区进行读且操作(目的)
下面是位带操作的一些说明
二、计算公式
字节地址为A,比特位序号为n(0<=n<=7)
说明:“*4”表示一个字为4个字节,“*8”表示一个字节中有8个比特。
将上述的外设位带区和SRAM位带区进行统一,得到下面的公式:
((addr&0xF0000000)+0x02000000+((addr & 0x000FFFFF)<<5)+(bitnum<<2))
其中4*8=32=2的5次方,4=2的2次方,相当于左移了5位和2位
公式解析
- add &0xF000 0000:目的是取出4和2,用于区分是外设还是SRAM。然后再加上0x2000000就等于外设/SRAM位带别名区的起始地址。
- add &0x000FFFFF:屏蔽掉高3位。外设位带区的最高地址为0x400F0000,SRAM位带区的最高地址为0x200F 0000,(0x400F 0000 - 0X4000 0000)与(0x200F 0000-0x2000 0000)在求偏移地址相减的时候只有低五位有效,所以就把剩下的高3位屏蔽掉,剩下的5位和F做与运算即可。
三、举例
假如要操作GPIOH的ODR寄存器的10位,就可以通过位带操作来访问
//1.宏定义ADDR
#define GPIOH_ODR_ADDR (GPIOH_BASE+0X14)
//2.求出位带别名区的地址 传进两个参数 参数一:ADDR 参数二:位数(即公式里面的n)
#define BITBAND(addr,bitnum) ((addr&0xF0000000)+0x02000000+((addr & 0x000FFFFF)<<5)+(bitnum<<2))
//3.把求出来的位带别名区(立即数)强制类型转换为指针,编译器才知道是地址
//即将BITBAND传入MEM_ADDR中
#define MEM_ADDR(addr) (*(volatile unsigned long *)(addr))
假设LED_GPIO_Config()是LED灯初始化程序
此处重点是说明位带的知识点,详情可以查看我的上一篇文章:
STM32F429--标准库点亮LED灯
https://blog.csdn.net/ABCisCOOL/article/details/106170244
此时在main函数里面直接调用即可,把
void main(void)
{
while(1)
{
LED_GPIO_Config</