STM32------位绑定

学习STM32首先要理解的就是对寄存器的操作了,因为在STM32中对各IO口的操作实际就是对寄存器中各个位的操作。

在看了一个关于寄存器位绑定操作的教学视频后仍然是一头雾水,只能去网上查询各种资料,如比较有用的有《STM32位绑定操作的理解》,加上其他文章,形成了自己对位绑定的理解。

概念:

把对寄存器某一位的操作,映射到某个内存地址(只有最低位有效)

好处:

代码效率更高,速度更快,更改的时候不需要多读一次寄存器。


STM32将寄存器映射到了位带区(bit_band region),这样就可以通过统一的线性寻址空间直接操作寄存器了,这个空间就是0x00000000~0xFFFF FFFF共4GB大小,寄存器只是其中一小部分,其他包括程序存储区、数据存储区、输入输出端口等。这样的映射有两段,分别是0x2000 0000~0x200F FFFF(SRAM)及0x4000 0000~0x400F FFFF(片上外设)。经转换可知,这两个地址分别都有1MB(注意是字节)那么大,如果转换成bit的话应该是8Mb。

 可这样操作还是不方便,如果要操作某一位需要进行位运算才行,回来几次挺浪费计算资源的。因为CPU是32位的,最方便快捷的是直接操作一个32位的地址,比如0x4200 ABCD这样,对这个地址赋值是最快捷的操作,只要一条指令。于是STM32又设计出别名区(Alias region)的概念,将一个32位地址空间对应到位带区(bit_band region)中的一个位。32位是STM32 CPU能独立访问的地址空间(称为字,即4个字节),将这个地址空间的起始位(bit0,其他bit1~bit31忽略)内容设为0或1就等于对位带区的相应位进行了操作,也相当于对寄存器进行了操作。

映射关系是:


很明显,这样的别名区(Alias region)一样会有2个,而且都是32MB,是位带区1MB的32倍,为什么是32倍呢?因为位带区是以位为单位,每8个位(一字节)有个地址,而别名区是以字为单位,一个字等于4个字节共32位,才用于表示一个位带区的位,就相当将位带区膨胀32倍,才是别名区的大小。理解这个32倍数的由来有助掌握后面的公式中的参数。

 有图是这样描述别名区与位带区的关系:


从图可知,位带区0x2000 0000的第0位对应别名区地址0x22000000~0x2200 0003这4个字节,需要指出的是0x2200 0001、0x2200 0002、0x2200 0003这样的地址是不能直接被访问的,只有0x2200 0000、0x2200 0004、0x2200 0008…这样的起始地址(其实是4的倍数)才能被访问,其实我们所说的别名区的地址映射就是计算这样的起始地址。理解这一点也有助于后面地址计算公式的掌握。

 

好了,上面是理解的基础,下面才是具体的别名区起始地址的计算。首先我们要有一个概念是,一般计算应用关于寻址的计算都这样的:

 

要计算的地址=基地址+偏移量

 

具体到STM32别名区起始地址的计算官方给的计算公式是:

it_word_addr = bit_band_base + (byte_offset*32) +(bit_number*4) 

bit_word_addr:是位带区目标位映射到别名区的字的起始地址 

bit_band_base:是别名区的起始地址 

SRAM区所对应的起始地址为 0x2200 0000

片上外设区所对应的起始地址为 0x4200 0000

这两项都是一种规定,记住就行  

byte_offset:是位带区包含目标位的字节的地址偏移量。 

在SRAM位带区的偏移量为:(A-0x2000 0000),A为包含目标位字节的地址

在片上外设区所对应的偏移量为:(A-0x4000 0000),A为包含目标位字节的地址

byte_offset*32:是因为位带区的一个位要扩张到别名区的32个位,同样,一个位带区的地址也会扩张到别名区的32个地址。byte_offset*32表示前面已经占用的地址。  

bit_number:是目标位所在的位的位置(0-7)   

bit_number*4是因为 1bit位要占用四个地址单元(四个字节,32 bit位)

其实这个公式还有一个变异形式,也是有助于理解这一公式的:

it_word_addr = bit_band_base + ((byte_offset*8) + bit_number)*4

由于位带区每一个地址是8个位,所以(byte_offset*8)+ bit_number相当计算出了一个以字节为单位的偏移,再乘以4就是以字为单位的偏移了。

很明显,不管是哪个公式,都是基地址+偏移。


可以用作位绑定的内存区域:

片内内存区域、SRAM区 :0x2000 0000 ~ 0x200F FFFF 共1M

片上外设区域   :0x4000 0000 ~ 0x400F FFFF 共1M

公式:

SRAM区映射的地址

AliasADDr = 0x22000000 + ((A - 0x20000000) * 8 + n) * 4 = 0x22000000 + ((A - 0x20000000) * 32 + n * 4   ,  n=0~7

片上外设区映射的地址

AliasADDr = 0x42000000 + ((A - 0x20000000) * 8 + n) * 4= 0x42000000 + ((A - 0x20000000) * 32 + n * 4

再就是尝试着算一下某一个端口的别名区的地址吧,以GPIOA->IDR第11位为例:

GPIOA的地址就是GPIOA_BASE,GPIOA_BASE=APB2PERIPH_BASE+0x0800,而APB2PERIPH_BASE= PERIPH_BASE + 0x1 0000,PERIPH_BASE= 0x40000000(就上面说的片上外设的位带区起始地址),那么GPIOA的起始(基)地址就是0x4000 0000+0x1 0000+0x0800=0x4001 0800,这些GPIOA_BASE、APB2PERIPH_BASE、PERIPH_BASE的定义都可以通过头文件stm32f10x_map.h查询可知,其实就是理解为STM32的一种定义就可以了。

通过参考手册可知GPIOx_IDR的偏移为0x08,IDR第11位其实就是相当于偏移再加1的第3位(这里需要好好理解),代入上面的公式就是:

AliasAddr=0x4200 0000 + (0x4001 0800+0x08+1-0x4000 0000)*32+3*4   

或者:AliasAddr=0x4200 0000 + (0x4001 0800+0x08-0x4000 0000)*32+11*4 

      =0x42000000 +Ox1 0809*32+12

      =0x4221 0120+12

      =0x4221 012C

直接对这个地址的内存起始位(bit0)操作就相当于对GPIOA->IDR第11位进行操作。

 

再来算一个,计算GPIOC->ODR的第15位的别名地址:

GPIOC_BASE= APB2PERIPH_BASE++0x1000,APB2PERIPH_BASE= PERIPH_BASE + 0x1 0000,PERIPH_BASE= 0x4000 0000

GPIOC_BASE=0x4000 0000+0x1 0000+0x1000=0x4001 1000

通过参考手册可知GPIOx_ODR的偏移为0x0C,ODR第15位其实就是相当于偏移再加1的第7位,代入上面的公式就是:

AliasAddr=0x4200 0000 + (0x4001 1000+0x0C+1-0x4000 0000)*32+7*4

      =0x42000000 +Ox1 100D*32+28

      =0x4222 01BC


好了接关就是理解关于位绑定的宏定义了(只列出了GPIOA的部分): 

[objc]  view plain  copy
  1. #define GPIOA_ODR_A  (GPIOA_BASE+0x0C)  
  2. #define GPIOA_IDR_A  (GPIOA_BASE+0x08)   
  3. #define BitBand(Addr,BitNum)    *((volatileunsigned long*)((Addr&0xF0000000)+0x2000000+((Addr&0xfffff)<<5)+(BitNum<<2)))   
  4. #define PAout(n)   BitBand(GPIOA_ODR_A,n)  
  5. #define PAin(n)    BitBand(GPIOA_IDR_A,n)  

BitBand()其实就是刚才公式的公式,但其通过位运算同时支持Ox20000000及Ox4000 0000开始的位带区计算,另将乘以32及乘以4改成位操作<<5及<<2了(左移不溢出的情况下)。Volatile则通知编译器不要优化此语句,每次都从所指内存存取数值。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值