您现在的位置是:首页 >技术交流 >【STM32】基础知识 第七课 存储器映射 & 寄存器映射网站首页技术交流

【STM32】基础知识 第七课 存储器映射 & 寄存器映射

我是小白呀 2023-05-26 08:00:03
简介【STM32】基础知识 第七课 存储器映射 & 寄存器映射

STM32 寻址范围

32 位的单片机可以友 32 根地址线 (每根地址线有两种转态: 导通或不导通). 单片机内存地址访问的存储单元是按字节编址的 (而不是 bit)

地址线根数地址编号 (二进制)地址编号数 (即内存大小)
10, 12
200, 014
3000, 001, 010, 011, 100, 101, 110, 1118
n 2 n 2^n 2n

STM32 寻址大小: 2 32 = 4 G 2^{32} = 4G 232=4G (字节)
STM 寻址范围: 0x0000 0000~0xFFFF FFFF

STM32 存储器映射

存储器映射

存储器指可以存储数据的设备, 本身没有地址信息, 对存储器分配地址的过程称为存储器映射.

存储器功能划分 (F1 为例)

ST 将 4GB (2^32) 地址空间分成 8 个块.

存储块功能地址范围
Block 0Code (Flash)0x0000 0000 ~ 0x1FFF FFFF (512 MB)
Block 1SRAM0x2000 0000 ~ 0x3FFF FFFF (512 MB)
Block 2片上外设0x4000 0000 ~ 0x5FFF FFFF (512 MB)
Block 3FSMC Bank1&20x6000 0000 ~ 0x7FFF FFFF (512 MB)
Block 4FSMC Bank3&40x8000 0000 ~ 0x9FFF FFFF
Block 5FSMC 寄存器0xA000 0000 ~ 0xBFFF FFFF
Block 60xC000 0000 ~ 0xDFFF FFFF (512 MB)
Block 7Cortex M3 内部外设0xE000 0000 ~ 0xFFF FFFF (512 MB)

Block 0

Block0 (FLASH) 功能划分:

存储块功能地址范围
Block 0FLASH 或系统存储器别名区0x0000 0000 ~ 0x0007 FFFF (512 KB)
Block 0保留0x0008 0000 ~ 0x07FF FFFF
Block 0用户 FLASH, 用于存储用户代码0x0800 0000 ~ 0x0807 FFFF (512 KB)
Block 0保留0x0808 0000 ~ 0x1FFF EFFF
Block 0系统存储器, 存储出厂 Bootloader0x1FFF F000 ~ 0x1FFF F7FF (2 KB)
Block 0选项字节, 配置读保护等0X1FFF F800 ~ 0x1FFF F80F (16 B)
Block 0保留0x1FFF F810 ~ 0x1FFF FFFF

Block 1

Block1 (SRAM) 功能划分:

存储块功能地址范围
Block 1SRAM0x2000 0000 ~ 0x2000 FFFF (64 KB)
保留0x2001 0000 ~ 0x3FFF FFFF

Block 2

存储块功能地址范围
Block 2APB1 总线外设0x4000 0000 ~ 0x4000 77FF
Block 2保留0x4000 7800 ~ 0x4000 FFFF
Block 2APB2 总线外设0x4001 0000 ~ 0x4000 3FFF
Block 2保留0x4001 4000 ~ 0x4001 7FFFF
Block 2AHB 总线外设0x4001 8000 ~ 0x4002 33FF
Block 2保留0x4002 3400 ~ 0x5FFF FFFF

STM32 寄存器映射

寄存器映射

寄存器 (Register) 是单片机内部一种特殊的内存, 可以实现对单片机各个功能的控制.

简单来说: 寄存器就是单片机内部的控制机构.

STM32 寄存器分类:

大类小类说明
内核寄存器内核相关寄存器包含 R0~R15, xPSR, 特殊功能寄存器等
内核寄存器中断控制寄存器包含 NVIC 和 SCB 相关寄存器, NVIC 有: ISER, ICER, ISPR, IP 等. SCB 有: VTOR, AIRCR, SCR 等
内核寄存器SysTick 寄存器包含 CTRL, LOAD, VAL 和 CALIB 四个寄存器
内核寄存器内存保护寄存器可选功能, STM32F103 没有
内核寄存器调试系统寄存器ETM, ITM, DWT, IPIU 等相关寄存器
外设寄存器包含 GPIO, UART, IIC, SPI, TIM, DMA, ADC, DAC, RTC, I/WWDG, PWR, CAN, USB 等各种外设寄存器

寄存器映射 (F1 为例)

寄存器是特殊的存储器, 给寄存器地址命名的过程, 就叫寄存器映射.

寄存器地址映射寄存器名字
0x4001080C给寄存器地址命名GPIOA_ODR

寄存器映射举例

直接操作寄存器地址:

*(volatile unsigned int*)(0x4001 080C) = 0xFFFF;

定义一个名字后再操作:

#define GPIOA_ODR *(volatile unsigned int*)(0x4001080C)

GPIOA_ODR = 0XFFFF;
  • 使用volatile 关键词对寄存器地址进行修饰, 告诉编译器, 该地址运行过程中随时可能变化, 编译时不要优化该地址
  • GPFDAT 宏定义代表了某寄存器中的值

寄存器地址计算

为了方便编写代码及使用, 我们将寄存器地址分为三个部分:

  1. 总线基地址 (BUS_BASE_ADDR)
  2. 外设基于总线基地址的偏移量 (PERIPH_OFFSET)
  3. 寄存器相对外设基地址的偏移量 ( REG_OFFSET)

寄存器地址 = BUS_BASE_ADDR + PERIPH_OFFSET + REG_OFFSET

总线基地址:

总线基地址偏移量
APB 10x4000 00000
APB 20x4001 00000x1 0000
AHB0x4001 80000x1 8000

APB1 总线的基地址, 也叫外设基地址 (PERIPH_BASE).

此表的偏移量: 是相对外设基地址 (PERIPH_BASE) 来说的.

GPIO 外设基地址及偏移量

所属总线外设基地址偏移量
APB 2 0x4001 0000GPIOA0x4001 08000x800
APB 2 0x4001 0000GPIOB0x4001 0C000xC00
APB 2 0x4001 0000GPIOCox4001 1000
0x1000
APB 2 0x4001 0000GPIODox4001 1400
0x1000
APB 2 0x4001 0000GPIOEox4001 1800
0x1000
APB 2 0x4001 0000GPIOFox4001 1C00
0x1000
APB 2 0x4001 0000GPIOGox4001 2000
0x2000

此表的偏移量: 是相对 APB2 外设基地址 (APB2PERIPH_BASE) 来说的.

寄存器地址及偏移量

所属外设寄存器地址偏移量
GPIOA 0x4001 0800GPIOA_CRL0x4001 08000x00
GPIOA 0x4001 0800GPIOA_CRH0x4001 08040x04
GPIOA 0x4001 0800GPIOA_IDR0x4001 08080x08
GPIOA 0x4001 0800GPIOA_ODR0x4001 080C0x0C
GPIOA 0x4001 0800GPIOA_BSRR0x4001 08100x10
GPIOA 0x4001 0800GPIOA_BRR0x4001 08140x14
GPIOA 0x4001 0800GPIOA_LCKR0x4001 08180x18

寄存器地址计算过程

  1. 获取总线基地址, APB2 总线基地址: 0x4001 0000
  2. 获取外设地址偏移量, GPIOA 相对 APB2 总线偏移量是: 0x800
  3. 获取寄存器地址偏移量, ODR 相对 GPIOA 外设地址的偏移量是 0x0C

寄存器地址 = BUS_BASE_ADDR+ PERIPH_OFFSET+ REG_OFFSET

GPIOA_ODR = 0x4001 0000+0x800+0x0C=0x4001 080C

使用结构体映射寄存器

定义结构体:

typedef struct{
__IO uint32_t CRL;
__IO uint32_t CRH;
__IO uint32_t IDR;
__IO uint32_t ODR;
__IO uint32_t BSSR;
__IO uint32_t BRR;
__IO uint32_t LCKR;
}GPIO_TypeDEF;  // 声明变量

例子:

GPIOA_BASE: 0x4001 0800
# define GPIOA ((GPIO_TypeDef*)GPIOA_BASE)
&GPIOA->CRL: 0x4001 0800
&GPIOA->CRH: 0x4001 0804
&GPIOA->IDR: 0x4001 0808
&GPIOA->ODR: 0x4001 080C

// 实际应用
GPIOA->ODR = 0xFFFF;

STM32F103xe.h 主要组成部分

文件主要组成部分说明
stm32f103xe.h中断编号定义定义 IRQn_Type 枚举类型, 包含 STM32F103 内部所有中断编号 (中断号), 方便后续编写代码
stm32f103xe.h外设寄存器结构体类型定义以外设为单位, 使用结构体类型定义每个外设所有寄存器, 方便寄存器映射
stm32f103xe.h寄存器映射1. 定义总线地址和外设基地址
2. 使用外设结构体类型定义将外设基地址强制转换成结构体指针, 完成寄存器映射
stm32f103xe.h寄存器位定义定义外设寄存器每个功能位的位置及掩码
stm32f103xe.h外设判定判断某个外设是否合法 (即是否存在改外设)

出处: 笔记摘自正点原子

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。