您现在的位置是:首页 >技术交流 >【STM32】基础知识 第七课 存储器映射 & 寄存器映射网站首页技术交流
【STM32】基础知识 第七课 存储器映射 & 寄存器映射
【STM32】基础知识 第七课 存储器映射 & 寄存器映射
STM32 寻址范围
32 位的单片机可以友 32 根地址线 (每根地址线有两种转态: 导通或不导通). 单片机内存地址访问的存储单元是按字节编址的 (而不是 bit)
地址线根数 | 地址编号 (二进制) | 地址编号数 (即内存大小) |
---|---|---|
1 | 0, 1 | 2 |
2 | 00, 01 | 4 |
3 | 000, 001, 010, 011, 100, 101, 110, 111 | 8 |
n | … | 2 n 2^n 2n |
STM32 寻址大小:
2
32
=
4
G
2^{32} = 4G
232=4G (字节)
STM 寻址范围: 0x0000 0000~0xFFFF FFFF
存储器映射
存储器指可以存储数据的设备, 本身没有地址信息, 对存储器分配地址的过程称为存储器映射.
存储器功能划分 (F1 为例)
ST 将 4GB (2^32) 地址空间分成 8 个块.
存储块 | 功能 | 地址范围 |
---|---|---|
Block 0 | Code (Flash) | 0x0000 0000 ~ 0x1FFF FFFF (512 MB) |
Block 1 | SRAM | 0x2000 0000 ~ 0x3FFF FFFF (512 MB) |
Block 2 | 片上外设 | 0x4000 0000 ~ 0x5FFF FFFF (512 MB) |
Block 3 | FSMC Bank1&2 | 0x6000 0000 ~ 0x7FFF FFFF (512 MB) |
Block 4 | FSMC Bank3&4 | 0x8000 0000 ~ 0x9FFF FFFF |
Block 5 | FSMC 寄存器 | 0xA000 0000 ~ 0xBFFF FFFF |
Block 6 | 空 | 0xC000 0000 ~ 0xDFFF FFFF (512 MB) |
Block 7 | Cortex M3 内部外设 | 0xE000 0000 ~ 0xFFF FFFF (512 MB) |
Block 0
Block0 (FLASH) 功能划分:
存储块 | 功能 | 地址范围 |
---|---|---|
Block 0 | FLASH 或系统存储器别名区 | 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 | 系统存储器, 存储出厂 Bootloader | 0x1FFF F000 ~ 0x1FFF F7FF (2 KB) |
Block 0 | 选项字节, 配置读保护等 | 0X1FFF F800 ~ 0x1FFF F80F (16 B) |
Block 0 | 保留 | 0x1FFF F810 ~ 0x1FFF FFFF |
Block 1
Block1 (SRAM) 功能划分:
存储块 | 功能 | 地址范围 |
---|---|---|
Block 1 | SRAM | 0x2000 0000 ~ 0x2000 FFFF (64 KB) |
保留 | 0x2001 0000 ~ 0x3FFF FFFF |
Block 2
存储块 | 功能 | 地址范围 |
---|---|---|
Block 2 | APB1 总线外设 | 0x4000 0000 ~ 0x4000 77FF |
Block 2 | 保留 | 0x4000 7800 ~ 0x4000 FFFF |
Block 2 | APB2 总线外设 | 0x4001 0000 ~ 0x4000 3FFF |
Block 2 | 保留 | 0x4001 4000 ~ 0x4001 7FFFF |
Block 2 | AHB 总线外设 | 0x4001 8000 ~ 0x4002 33FF |
Block 2 | 保留 | 0x4002 3400 ~ 0x5FFF FFFF |
寄存器映射
寄存器 (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 宏定义代表了某寄存器中的值
寄存器地址计算
为了方便编写代码及使用, 我们将寄存器地址分为三个部分:
- 总线基地址 (BUS_BASE_ADDR)
- 外设基于总线基地址的偏移量 (PERIPH_OFFSET)
- 寄存器相对外设基地址的偏移量 ( REG_OFFSET)
寄存器地址 = BUS_BASE_ADDR + PERIPH_OFFSET + REG_OFFSET
总线基地址:
总线 | 基地址 | 偏移量 |
---|---|---|
APB 1 | 0x4000 0000 | 0 |
APB 2 | 0x4001 0000 | 0x1 0000 |
AHB | 0x4001 8000 | 0x1 8000 |
APB1 总线的基地址, 也叫外设基地址 (PERIPH_BASE).
此表的偏移量: 是相对外设基地址 (PERIPH_BASE) 来说的.
GPIO 外设基地址及偏移量
所属总线 | 外设 | 基地址 | 偏移量 |
---|---|---|---|
APB 2 0x4001 0000 | GPIOA | 0x4001 0800 | 0x800 |
APB 2 0x4001 0000 | GPIOB | 0x4001 0C00 | 0xC00 |
APB 2 0x4001 0000 | GPIOC | ox4001 1000 | |
0x1000 | |||
APB 2 0x4001 0000 | GPIOD | ox4001 1400 | |
0x1000 | |||
APB 2 0x4001 0000 | GPIOE | ox4001 1800 | |
0x1000 | |||
APB 2 0x4001 0000 | GPIOF | ox4001 1C00 | |
0x1000 | |||
APB 2 0x4001 0000 | GPIOG | ox4001 2000 | |
0x2000 |
此表的偏移量: 是相对 APB2 外设基地址 (APB2PERIPH_BASE) 来说的.
寄存器地址及偏移量
所属外设 | 寄存器 | 地址 | 偏移量 |
---|---|---|---|
GPIOA 0x4001 0800 | GPIOA_CRL | 0x4001 0800 | 0x00 |
GPIOA 0x4001 0800 | GPIOA_CRH | 0x4001 0804 | 0x04 |
GPIOA 0x4001 0800 | GPIOA_IDR | 0x4001 0808 | 0x08 |
GPIOA 0x4001 0800 | GPIOA_ODR | 0x4001 080C | 0x0C |
GPIOA 0x4001 0800 | GPIOA_BSRR | 0x4001 0810 | 0x10 |
GPIOA 0x4001 0800 | GPIOA_BRR | 0x4001 0814 | 0x14 |
GPIOA 0x4001 0800 | GPIOA_LCKR | 0x4001 0818 | 0x18 |
寄存器地址计算过程
- 获取总线基地址, APB2 总线基地址:
0x4001 0000
- 获取外设地址偏移量, GPIOA 相对 APB2 总线偏移量是:
0x800
- 获取寄存器地址偏移量, 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 | 外设判定 | 判断某个外设是否合法 (即是否存在改外设) |
出处: 笔记摘自正点原子