STM32——HAL库中寄存器地址名称映射分析

前言

本篇文章是为了明白HAL 库中那些结构体是怎么与寄存器地址对应起来的。部分知识参考正点原子资料。

一、HAL库中寄存器地址名称映射分析

最根本的单片机开发就是直接操作寄存器的值,给这些位赋值,但是32单片机的寄存器太多,所以MDK就使用结构体将这些寄存器组织在一起。那么只要我们修改结构体的变量就可以修改对应寄存器的值。这些结构体的关联组织是在stm32f1xx.h 的头文件中完成的。
每个寄存器的地址都是偏移过来的,以GPIO为例,它的基地址是由 APB2 总线的基地址+GPIOA 在 APB2 总线上的偏移地址决定的。同理依次类推,我们便可以算出 GPIOA 基地址。
GIPO的结构体是根据GPIO的地址来定义的,GPIO的地址是从GPIO基地址偏移过来的,GPIO的基地址是从时钟线的基地址偏移过来的,时钟线的地址是由PERIPH基地址偏移的,如下所示:

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;

我们跳转GPIOA的定义

#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)

这个宏是将GPIOA的基地址强转为结构体指针,我们继续跳转GPIOA_BASE

#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800) 

这个宏是将APB2时钟线的地址偏移0x0800得到的GPIOA基地址,我们以此类推依次跳转

#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) 
#define PERIPH_BASE ((uint32_t)0x40000000)

最后得到始终总线的基地址
其他外设也是一样。

二、计算寄存器地址

计算寄存器的地址:(以GPIOA为例)
GPIOA 的寄存器的地址=GPIOA 基地址+寄存器相对 GPIOA 基地址的偏移值
这个偏移值在上面的寄存器地址映像表中可以查到。

我们对应好第一个地址,结构体的地址是连续的,而GPIOA的类型是结构体指针,每个成员变量偏移0x04,寄存器地址映像顺序与结构体中的IO口的成员变量的顺序是一样的,加上偏移,那么结构体中的成员变量的地址都一一对应。

后面关于MDK如何组织代码我们就不总结了,在这里简单说一下,对于变量、函数等我们选中右键GO TO DEFINED就可以跳转到定义处和引用处,然后根据定义范围来赋值或使用,其他的软件小妙招之后可以简单总结如debug、configuration等应用和配置。