简述c语言对寄存器封装的原理,STM32------C语言对寄存器的封装

本文介绍了STM32中如何使用固件库操作GPIO寄存器,通过定义GPIO内存块的首地址和结构体简化寄存器的访问。讲解了GPIO口的地址映射,并通过实例展示了如何设置GPIO_MODER寄存器。同时,解释了STM32内部的总线结构和地址空间,以及如何通过总线寻址找到外设的寄存器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为了学习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 intuint32;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 intuint32;2 typedef unsigned short intuint16;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)

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值