. 使用KEIL5开发STM32可以使用"GPIOB->ODR"这种方式来给GPIOB的寄存器ODR赋值,因为在STM32中同属于一个外设的所有寄存器地址基本是相邻的(有些会有保留寄存器),因此我们可以借助C语言里面的结构体成员地址递增的特点来将某个外设的所有寄存器写入到一个结构体里面,然后定义一个结构体指针指向这个外设的寄存器基地址,这样我们就可以通过这个结构体指针来访问这个外设的所有寄存器。
STM32寄存器操作
ST官方为STM32系列处理器都编写了一个stm32f10x.h的文件,通过这个文件定义了STM32的所有外设寄存器。通过引用这个.h文件,我们可以在C文件中方便的找到对应的寄存器。
GPIOE->CRL&-0XFFOFFFFF;
GPIOE->CRL=0X00300000; //PE5推挽输出
GPIOE->ODR=1<<5; //PE5输出高
可以看出“GPIOE”是个宏定义,是一个指向地址 GPIOE_BASE 的结构体指针,结构体为
GPIO_TypeDef, GPIO_TypeDef 和 GPIOE_BASE 的定义如下
#define GPIOE ((GPIO TypeDef *) GPIOE BASE)
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;
#define GPIOE_BASE (APB2PERIPH_BASE + 0x1800)
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
#define PERIPH_BASE ((uint32_t)0x40000000)
根据C语言里面的结构体成员地址递增的特点,所以结构体定义的寄存器是按照其地址顺序从小到大排序的。GPIOE_BASE就是GPIOE的基地址,我们在上面定义的时候采用了地址偏移的方式定义,下面我们详细算一下GPIOE_BASE代表的地址。
GPIOE_BASE=APB2PERIPH_BASE+0x1800
= PERIPH_BASE + 0x10000 + 0x1800
=0x40000000 + 0x10000 + 0x1800
=0x40011800
GPIOE_BASE 的基地址为 0x40011800,宏 GPIOE 指向这个地址,
因此 GPIOE 的寄存器CRL 的地址就是 0X40011800,
寄存器 CRH 的地址就是 0X40011800+4=0X40011804,其他寄存器地址以此类推。
我们要操作 GPIOE 的 ODR 寄存器的话就可以通过“GPIOE->ODR”来实现,这个方法是借助了结构体成员地址连续递增的原理。
来源:CSDN
作者:小牟加油
链接:https://blog.csdn.net/muchunpeng/article/details/104698641