STM32笔记(四)位带操作介绍

简介

位带操作就是对可以单一的比特bit进行读写,在51单片机中可以用关键字sbit来实现位定义,在STM32单片机中就没有这样的关键字,取而代之的是通过访问位带别名区来实现位带操作的。

在 STM32 中,有两个地方实现了位带,一个是 SRAM 区的最低 1MB 范围,另一个是片内外设
的最低 1MB 范围,两个区中的地址除了可以像普通的 RAM 一样使用外,它们还都有自
己的“位带别名区,”位带别名区“把这 1MB 的空间的每一个位膨胀成一个 32 位的字,当
访问位带别名区的这些字时,就可以达到访问位带区某个比特位的目的。
在这里插入图片描述

外设位带区

对于STM32F103系列来说,外设位带区的地址是: 0X40000000~0X40100000,大小为 1MB,这些地址上包含了F103系列各种容量大小单片机的寄存器。
外 设 位 带 区 经 过 膨 胀 后 的 位 带 别 名 区 地 址 为 :0X42000000~0X43FFFFFF
STM32 的全部寄存器都可以通过访问位带别名区的方式来达到访问原始寄存器比特位的效果,而51单片机只有部分寄存器可以,但一般我们不会以纯寄存器进行开发,如果项目需要频繁的操作各种IO口的时候,位带操作的作用就来了。

SRAM位带区

SRAM 的位带区的地址为: 0X2000 0000~X2010 0000,大小为 1MB,
膨胀后的位带别名区地址为: 0X2200 0000~0X23FF FFFF,大小为 32MB,
一般很少用位带操作操作SRAM区的单个比特。

位带操作的膨化对应关系

在这里插入图片描述

外设位带别名区地址映射

对于片上外设位带区的某个比特,记它所在字节的地址为 A,位序号为 n(0<=n<=7),则该比特在别名区的地址为:

 AliasAddr = 0x42000000 + (A-0x40000000)*8*4 + n*4

其中
0X42000000 是外设位带别名区的起始地址
0x40000000 是外设位带区的起始地址

SRAM 位带别名区地址

对于 SRAM 位带区的某个比特,记它所在字节的地址为 A,位序号为 n(0<=n<=7),则该比特在别名区的地址为:

AliasAddr = 0x22000000 + (A-0x20000000)*8*4 + n*4

0x22000000 是SRAM位带别名区的起始地址
0x20000000 是SARM位带区的起始地址

统一的地址转化公式

为了方便操作,通常把这两个公式合并成一个公式,把“位带地址+位序号”转换成别名区地址统一成一个宏

// 把“位带地址+位序号”转换成别名地址的宏
2 #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x02000000+((addr &
0x00FFFFFF)<<5)+(bitnum<<2))

从左往右看
1、addr & 0xF0000000 主要是为了取出addr的头四位,也就是取出SRAM位带别名区的2或者外设位带别名区的4
2、+ 0x02000000
外 设 位 带 区 经 过 膨 胀 后 的 位 带 别 名 区 地 址 为 :0X42000000~0X43FFFFFF
膨胀后的位带别名区地址为: 0X2200 0000~0X23FF FFFF
很明显,每一个膨化后的地址从左往右第二位上都有2,所以这里就要加上0x02000000
3、addr & 0x00FFFFFF
通过前面两步,已经把位带别名区的十六位进制初始地址的头两位给确定了,我们不希望在后面的加减中重复的取到头两位的地址,所以通过这个操作把头两位给屏蔽掉以免影响后续的地址的叠加
4、<<5 与 <<2
<<5 相当于*8*4,<<2 相当于*4

利用位带操作单独操作每一个GPIO输入输出

#define GPIOB_ODR_Addr (GPIOB_BASE + 0x0C)
//设置GPIOB_ODR的位带操作,控制GPIO的输出,bitnum是引脚号如PB1,PB2
#define PBout(bitnum)   *(unsigned int *)((GPIOB_ODR_Addr & 0xF0000000)+0x02000000+((GPIOB_ODR_Addr & 0x00FFFFFF)<<5)+(bitnum<<2))
//这里用*(unsigned int *)将地址转化成可操作的寄存器

#define GPIOA_IDR_Addr (GPIOA_BASE + 0x08)
//设置GPIOA_IDR的位带操作,也就是控制GPIO的输入
#define PAin(bitnum)   *(unsigned int *)((GPIOA_IDR_Addr & 0xF0000000)+0x02000000+((GPIOA_IDR_Addr & 0x00FFFFFF)<<5)+(bitnum<<2))
原创文章 12 获赞 0 访问量 1106

猜你喜欢

转载自blog.csdn.net/zcy_cyril/article/details/105880911