STM32------C语言对寄存器的封装

为了学习STM32时比较踏实,有必要了解固件库底层是怎么操作的

GPIOA~F首地址

GPIOA 0x4002 0000
GPIOB 0x4002 0400
GPIOC 0x4002 0800
GPIOD 0x4002 0C00
GPIOE 0x4002 1000
GPIOF 0x4002 1400

 

 

 

 

 

 

以GPIOF口的GPIO_OSPEEDR寄存器为例

 1 typedef unsigned int uint32;
 2 //GPIOF内存块的首地址
 3 #define   GPIOF_BASE     (0x4002 1400)
 4 //GPIO口寄存器
 5 #define   GPIO_MODER     *(uint32 *)(GPIO_BASE+0x00)
 6 #defien   GPIO_OTYPER    *(uint32 *)(GPIO_BASE+0x04)
 7 #define   GPIO_OSPEEDR   *(uint32 *)(GPIO_BASE+0x08)
 8 #define   GPIO_PUPDR     *(uint32 *)(GPIO_BASE+0x0C)
 9 #define   GPIO_IDR       *(uint32 *)(GPIO_BASE+0x10)
10 #define   GPIO_ODR       *(uint32 *)(GPIO_BASE+0x14)
11 #define   GPIO_LCKR      *(uint32 *)(GPIO_BASE+0x1C)
12 #define   GPIO_AFRL      *(uint32 *)(GPIO_BASE+0x20)
13 #define   GPIO_AFRH      *(uint32 *)(GPIO_BASE+0x24)

 这样的话,我们如果要令GPIO_MODE寄存器的值全为F,GPIO_MODE=0xFFFF FFFF.

像上面这样定义寄存器有一个缺点,就是这只是定义了一个GPIO口,如果要把所有GPIO口都定义了,那将会有很多这样的定义,这样太麻烦,而且也不太好阅读。为了方便定义寄存器,我将用结构体,从上面寄存器的偏移地址可以看出,每个寄存器都是一个接着一个有序的排列,这就类似于C语言中的结构体。所以我们可以利用结构体来简化定义。

 1 typedef unsigned int uint32;
 2 typedef unsigned short int uint16;
 3 #define GPIOA_BASE   (0x4002 0000)
 4 #define GPIOB_BASE   (0x4002 0400)
 5 #define GPIOC_BASE   (0x4002 0800)
 6 typedef struct
 7 {
 8     uint32 GPIO_MODER;
 9     uint32 GPIO_OTYPER; 
10     uint32 GPIO_OSPEEDR;   
11     uint32 GPIO_PUPDR; 
12     uint32 GPIO_IDR;   
13     uint32 GPIO_ODR;   
14     uint32 GPIO_LCKR;  
15     uint16 GPIO_AFRL;   
16     uint16 GPIO_AFRH;   
17 }GPIO_TypeDef;
18 
19 #define GPIOA  (GPIO_TypeDef *)GPIOA_BASE;
20 #define GPIOB  (GPIO_TypeDef *)GPIOB_BASE;
21 #define GPIOC  (GPIO_TypeDef *)GPIOC_BASE;
22 
23 GPIOA->GPIO_MODER=0xffffff;

 首先,我们定义每个GPIO的内存块的首地址,然后定义一个结构体,里面的成员要按顺序写好寄存器的别名,接着我们用第19的宏定义,将GPIO的内存块首地址强制转换成指向结构体的指针,也就是结构体的首地址就是GPIO内存块的首地址,最后我们可以利用成员符号,对每个寄存器进行写入数据或者读取数据。

STM32中固件库到底是什么 

STM32内部里有一个叫总线的东西有APB1,APB2,APB3,AHB1,AHB2总线,总线也是有地址的,固件库是怎么利用总线的地址来寻到每个寄存器呢?

 1 #define PERIPH_BASE           ((uint32_t)0x40000000)
 2 #define APB1PERIPH_BASE       PERIPH_BASE
 3 #define APB2PERIPH_BASE       (PERIPH_BASE + 0x00010000)
 4 #define AHB1PERIPH_BASE       (PERIPH_BASE + 0x00020000)
 5 #define AHB2PERIPH_BASE       (PERIPH_BASE + 0x10000000)
 6 
 7 #define GPIOA_BASE            (AHB1PERIPH_BASE + 0x0000)
 8 #define GPIOB_BASE            (AHB1PERIPH_BASE + 0x0400)
 9 #define GPIOC_BASE            (AHB1PERIPH_BASE + 0x0800)
10 #define GPIOD_BASE            (AHB1PERIPH_BASE + 0x0C00)
11 #define GPIOE_BASE            (AHB1PERIPH_BASE + 0x1000)
12 #define GPIOF_BASE            (AHB1PERIPH_BASE + 0x1400)
13 #define GPIOG_BASE            (AHB1PERIPH_BASE + 0x1800)
14 #define GPIOH_BASE            (AHB1PERIPH_BASE + 0x1C00)
15 #define GPIOI_BASE            (AHB1PERIPH_BASE + 0x2000)
16 #define GPIOJ_BASE            (AHB1PERIPH_BASE + 0x2400)
17 #define GPIOK_BASE            (AHB1PERIPH_BASE + 0x2800)

 原理跟上面不一样只不过,固件库利用总线的首地址来寻找每个外设的地址。 

 

 

 

 

 

posted @ 2018-09-05 17:10  crazyyang  阅读(1900)  评论(0编辑  收藏  举报