STM32F1学习-深入理解存储器(存储器映射以及bit-band)

时间:2024-05-18 20:26:11

1.存储器映射

STM32F1的系统结构

STM32F1学习-深入理解存储器(存储器映射以及bit-band)

存储器映射

STM32F1学习-深入理解存储器(存储器映射以及bit-band)

STM32F1的存储器的映射

存储器映射是指把芯片中或芯片外的FLASH,RAM,外设,BOOTBLOCK等进行统一编址。即用地址来表示对象。这个地址绝大多数是由厂家规定好的,用户只能用而不能改。用户只能在挂外部RAM或FLASH的情况下可进行自定义。

STM32F1学习-深入理解存储器(存储器映射以及bit-band)

从系统结构图中我们可以看出,所有内部设备都是AHB System Bus上,AHB系统总线又分成两个连接的桥,APB1的操作速度限于36MHZ,APB2的操作速度是全速(最高72MHZ)可以很清晰的从图中看出每个桥连接的内部设备。

寄存器(GPIOX)组起始地址

STM32F1学习-深入理解存储器(存储器映射以及bit-band)

我们以GPIOA为例子。首先我们得明确一点:GPIOA是挂载在APB2上,APB2是从AHB系统总线中分出来的。

 

从stm32f10x.h头文件中,我们可以得到一些程序段:

typedef unsigned int uint32_t;//说明CRL等寄存器是十六位的。

typedef struct
{
  __IO uint32_t CRL;
  __IO uint32_t CRH;
  __IO uint32_t IDR;
  __IO uint32_t ODR;
  __IO uint32_t BSRR;
  __IO uint32_t BRR;
  __IO uint32_t LCKR;
} GPIO_TypeDef;

首先我们明确GPIO_TypeDef是一个结构体变量。

下面的程序段最好从下往上看更好理解。

#define PERIPH_BASE((uint32_t)0x40000000) 

#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) 

#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)

#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)

PERIPH_BASE 是外设基地址,为了便于我们可以把这个比作是AHB系统总线的地址,那么APB2的地址就是在外设基地址的基础上加上偏移量。由程序段看出来偏移量是0x10000,同样的理解。GPIOA的地址就是在APB2的地址的地址基础上加上一个偏移地址,由程序段中可以看出是0x800。所以我们可以得到GPIOA的起始地址地址是0x4000_0000+0x1_0000+0x0800 = 0x4001_0800。

从STM32的中文参考手册中,我们看到CRL、CHL、IDR、ODR、BSRR、BRR、LCKR的偏移量都是004H。

因为CRL、CHL、IDR、ODR、BSRR、BRR、LCKR寄存器都定义的是16位的地址,所以定义32的地址需要

这么理解:一个地址存储八位信息,(char一个字节是八位最大的整数是2^8-1)比如:0x4001_0800存储8位的信息,0x4001_0801存储8位信息......0x4001_0804存储8位信息。一共存储32位信息。GPIOx的某一位的CRL需要4个位(两个位控制模式,两个位控制速度)来控制。4*8(CRL只控制低8位)=32。

因此GPIOA各个寄存器的实际地址

寄存器                偏移地址         实际地址=基地址+偏移地址 

GPIOA->CRL     0x00  0x40010800+0x00 
GPIOA->CRH;   0x04   0x40010800+0x04 

GPIOA->IDR;     0x08   0x40010800+0x08 

GPIOA->ODR    0x0c  0x40010800+0x0c 

GPIOA->BSRR   0x10   0x40010800+0x10 

GPIOA->BRR     0x14   0x40010800+0x14

GPIOA->LCKR   0x18   0x40010800+0x18 

 

2.bit-band理解

 

Bit Banding功能是相对于以往能够进行bit操作的单片机而言的。通过Bit Banding功能可以像51单片机的bit操作一样。MCS51可以简单的将P1口的第2位独立作:P1.2=0;P1.2=1  就是这样把P1口的第三个脚(BIT2)置0或置1了。而现在STM32的位段、位带别名区就为了实现这样的功能。只不过他是为需要操作的地址(1字节)的每一个位(共8位)起个别名,分别对应别名区的一个字(word)。也就是别名区的大小是Bit Band的32倍。这样,32MB的别名区地址的操作,就是对相应Bit Band区的位的操作。Bit Banding功能是相对于以往能够进行bit操作的单片机而言的。

和bit-bind有关的寄存器

 

STM32F1学习-深入理解存储器(存储器映射以及bit-band)

 

STM32有两个Bit Band区域,分别是:

0x2000 0000——0x2010 0000:该地址是STM32的SRAM低1MB的地址区域;

0x4000 0000——0x4010 0000:该地址是STM32的Peripherals低1MB的地址区域;

另外,STM32还有两个对应的Bit Band区域的别名区,分别是:

0x2200 0000——0x23FF FFFF:共32MB的空间,对应相应1MB的每一个位;

0x4200 0000——0x43FF FFFF:共32MB的空间,对应相应1MB的每一个位;

 

接下来的问题是如何确定Bit Band区字节的位所对应的那个别名区的字(word)。Bit Band区和别名区是一一对应的,具体的公式为:

bit_word_addr=bit_band_base+ (byte_offset×32) + (bit_number×4);

bit_band_base:32MB别名区首地址;

byte_offset:1MB位段区偏移量,即为bit-band 区中包含目标位的字节的编号;

bit_number:位段中目标位的位位置(0-7);

 举个例子(通过别名区访问地址):

1、想操作SRAM中Bit Band区地址为 0x2000 0018字节的第2位

计算别名区对应子地址:0x2200 0000 +(18*32)+(2*4) = 0x2200 0248

所以,对0x2200 0248地址的操作,就是对0x2000 0018字节的第2位进行操作;

注意:别名字的位[31:1]在 bit-band 位上不起作用。写入 0x01 与写入 0xFF 的效果相同。写入0x00 与写入0x0E 的效果相同。

好了,整理了大概有5个小时,有部分是参考:

STM32F1学习-深入理解存储器(存储器映射以及bit-band)

【疑问】

可以bit-bind的区域是:0x2000_0000-0x2010_0000  和0x4000_0000-0x4010_0000。具体是哪些寄存器,在头文件怎么实现的?比如是0x40010800+0x0c是PAout(); 其他的寄存器是怎么实现的?

 

转自:https://blog.****.net/u013355826/article/details/51953250