野火霸天虎 STM32F407 学习笔记_2 寄存器介绍

寄存器

虽然正式编程没有必要用寄存器编程,通常都是库函数或者 hal 库。但是还是有必要学一下原理的。

寄存器映射

芯片视图如下。

丝印:芯片上印的信息。型号,内核,生产批次等。

引脚:左上角是有小圆点的,从左上-左下-右下-右上逆时针看。或者如果没有小圆点,把丝印方向摆正,从左上角开始看。

芯片内部组成:

寄存器映射:32位,232=4GB,因此所有程序都需要通过内存 4GB 去映射访问。

block7:M4 芯片内外设,比如一些通信总线这些都算外设。

block1:内存。

block0:代码。不过实际上由于设计工艺的问题,block0 block1 都只用了很少的一部分来存代码或者作为内存。

外设寄存器放在 block2 中。根据不同块速度不一样,又具体分为不同速度的外设(AHB APB)。

总线速度:AHB>APB2>APB1. APB1 是较低速的外设,包括 I2C UART SPI 看门狗等。

我们想要操作特定的外设,其实就是控制他的寄存器。控制寄存器就要找到寄存器相应的地址往里面写入数据,寄存器地址就是内存中的地址映射。

比如 GPIOF 我们想让其端口全部输出高电平。我们查找 stm32f407 手册,发现 GPIOF 的地址是 0x40021400,GPIOF 的 ODR(output data register)相对起始地址的偏移地址是14,则我们需要给 0x40021414 的地址写入数据 0xFFFF.

51 单片机库函数中封装的 reg51.h 中,利用 sfr 定义寄存器地址;而 stm32 库函数中使用宏定义,这些就是寄存器映射操作。对芯片里一个特殊功能的内存单元起别名的过程就是寄存器映射。 给这个地址再分配一个地址交重映射,stm32 中不咋常用。

C语言对寄存器的封装

这样逐个地址,哪怕已经进行了寄存器映射,还是很复杂。

c 语言库函数实际进行的封装操作是使用结构体批量定义。

c 复制代码
/* GPIO 外设基地址 */
#define GPIOA_BASE (AHB1PERIPH_BASE + 0x0000)
#define GPIOB_BASE (AHB1PERIPH_BASE + 0x0400)
#define GPIOC_BASE (AHB1PERIPH_BASE + 0x0800)
#define GPIOD_BASE (AHB1PERIPH_BASE + 0x0C00)
#define GPIOE_BASE (AHB1PERIPH_BASE + 0x1000)
#define GPIOF_BASE (AHB1PERIPH_BASE + 0x1400)
#define GPIOG_BASE (AHB1PERIPH_BASE + 0x1800)
#define GPIOH_BASE (AHB1PERIPH_BASE + 0x1C00)

/* GPIO 寄存器列表 */
typedef struct {
    uint32_t MODER; /*GPIO 模式寄存器 地址偏移: 0x00 */
    uint32_t OTYPER; /*GPIO 输出类型寄存器 地址偏移: 0x04 */
    uint32_t OSPEEDR; /*GPIO 输出速度寄存器 地址偏移: 0x08 */
    uint32_t PUPDR; /*GPIO 上拉/下拉寄存器 地址偏移: 0x0C */
    uint32_t IDR; /*GPIO 输入数据寄存器 地址偏移: 0x10 */
    uint32_t ODR; /*GPIO 输出数据寄存器 地址偏移: 0x14 */
    uint16_t BSRRL; /*GPIO 置位/复位寄存器低 16 位部分 地址偏移: 0x18 */
    uint16_t BSRRH; /*GPIO 置位/复位寄存器高 16 位部分 地址偏移: 0x1A */
    uint32_t LCKR; /*GPIO 配置锁定寄存器 地址偏移: 0x1C */
	uint32_t AFR[2]; /*GPIO 复用功能配置寄存器 地址偏移: 0x20-0x24 */
} GPIO_TypeDef;

/* 使用 GPIO_TypeDef 把地址强制转换成指针 */
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)
#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)
#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)
#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE)
#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE)
#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE)
#define GPIOH ((GPIO_TypeDef *) GPIOH_BASE)

所有外设都是如此,首先定义总线 APB AHB 地址,然后每个外设在其基础上进行偏移,每个外设的不同部分再在该外设基址上进行偏移。

相关推荐
我想我不够好。19 小时前
电工作业中元件的作用
学习
协同生态19 小时前
天锐绿盾新版注册机【仅用于个人学习,禁止其他用途】
学习
时空自由民.19 小时前
stm32FXX系列MCU汇编启动文件分析
汇编·stm32·单片机
Cuby!19 小时前
【AFDM与信号处理:论文阅读】仿射频分复用:扩展OFDM以实现场景灵活性和弹性
论文阅读·笔记·学习·信息与通信·信号处理
AAA阿giao20 小时前
从零开始学 React:用搭积木的方式构建你的第一个网页!
前端·javascript·学习·react.js·前端框架·vite·jsx
Arciab20 小时前
C++ 学习_流程控制
c++·学习
HyperAI超神经20 小时前
【vLLM 学习】vLLM TPU 分析
开发语言·人工智能·python·学习·大语言模型·vllm·gpu编程
小冷Hello20 小时前
迪文屏开发-多国语言-只需一组控件
stm32·单片机·嵌入式硬件
xiaoxiaoxiaolll20 小时前
前沿速递 | Adv. Eng. Mater.:基于LPBF与压力渗透的FeSi2.9-Bakelite多功能复合材料设计与性能调控
学习
Freshman小白20 小时前
《人工智能与创新》网课答案2025
人工智能·学习·答案·网课答案