STM32位绑定

学习STM32首先要理解的就是对各个寄存器的操作了,因为像STM32的高端单片机,由于带有非常丰富的外设资源,所以在STM32的管理上设计了非常的的寄存器来进行对资源的设置与管理。对于初学者面对这么多的寄存器,肯定会很兴奋,因为一个头三个大。但是当摸清楚里面的套路之后,你就会发现这些东西的神奇之处。我也是在慢慢的探索中。

玩过51单片机的人都知道,对51中的寄存器中的位操作,非常方便。但是对STM32中要对寄存器中的位操作,一般要进行三步操作,读 改 写,这样有些麻烦,而且效率也不高。但是在STM32-cortex系列中可以使用另一种机制,实现同样的效果,并且省事并且效率也高,那就是——位绑定。

对未绑定的理解就是把对寄存器某一位的操作,映射到某个内存地址(只有最低位有效)。

注:32位的芯片,虽然某一地址可以存放比较的的数,但是无论其他位为何值,只是对最低位有效

当然可以用来绑定的区域也是有限制的:   

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

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

STM32位绑定_第1张图片

STM32位绑定_第2张图片

虽然在片上的外设区域只有1M的大小,但是从上图中可以看出,这1M的大小已经完全可以将绝大部分的外设寄存器囊括其中。下面是对上图的表格表示

STM32位绑定_第3张图片

因为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倍数的由来有助掌握后面的公式中的参数。


在对地址进行映射的时候是要用一定的算法的,该算法简单,也是比较容易理解的。其公式如下:

        SRAM区映射的地址:AliasADDr = 0x22000000 + ((A - 0x20000000) * 8 + n) * 4 = 0x22000000 + ((A - 0x20000000) * 32         + n * 4                  A就是要进行映射的寄存器的地址,n 的取值范围是0~7     

        片上外设区映射的地址:AliasADDr = 0x42000000 + ((A - 0x40000000) * 8 + n) * 4= 0x42000000 + ((A - 0x40000000) * 32         + n * 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位)


说白了就是   基址+变址    


下面给出示例:

[cpp]  view plain  copy
  1. #include "stm32f10x_map.h"  
  2. #define PA0  GPIOA->BRR   
  3. #define PA1  GPIOA->BSRR   
  4. int main()  
  5. {  
  6.     u32 *PAO3 = (u32 *)(0x42000000 + (0x4001080c-0x40000000)*32 + 3*4);    //内存地址定义一个指针,PA端口输出 第3位  
  7.     u32 *PAI11 = (u32 *)(0x42000000 + (0x40010808-0x40000000)*32 + 11*4);      //绑定PA端口输入 第11位
  8.   
  9.    //配置     PA.3  推挽输出 50M  
  10.    //        PA.11 输入    
  11.     GPIOA->CRL = 0x0300;         //CNF0=00   MODE0=11  
  12.     GPIOA->CRH = 0x00400000;     //CNF0=01   MODE0=00 //模拟CNF0=00输入时,引脚变化不会引起IDR变化,浮空输入CNF0=01  
  13.    while(1)
  14.     {  
  15.         if(*PAI11==1)  *PAO3 = 1; else *PAO3 = 0; 
  16.     }  
  17.    return(1);  


说明:此文章是根据刘凯老师的讲解视频与前人的理解的基础上,对我自己的一个整理




你可能感兴趣的:(STM32位绑定)