单片机的程序编制主要是操作寄存器,而STM32功能更多,对应的寄存器也多,为了更好的管理和使用好寄存器,需要将这些寄存器进行管理和分配。以GPIOA为例;因为 GPIO 都是挂在 APB2 总线之上,所以它的基地址是由 APB2 总线的基地址+GPIOA 在 APB2 总线上的偏移地址决定的。同理依次类推,我们便可以算出 GPIOA 基地址了。
1、根据STM32存储器映射可以查到整个外设地址是----0x40000000(P41页)
#define PERIPH_BASE ((uint32_t)0x40000000)
2、APB2 总线的偏移地址是---0x10000
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
3、GPIOA的偏移地址是---- 0x0800(可以插P42页的地址映像表)
#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)
最后我们便可以算出 GPIOA 的基地址是:(也就是STM32的存储器映射)为了便于管理我们又引出了位绑定的概念(以后再学习)。
GPIOA_BASE= 0x40000000+0x10000+0x0800=0x4001080
查看官方手册
主函数如何定义呢?首先定义一个结构体
typedef struct //库函数
{
vu32 CRL; // 端口配置低寄存器 ;
vu32 CRH; // 端口配置高寄存器 ;
vu32 IDR; // 端口输入数据寄存器 ;
vu32 ODR; // 端口输出数据寄存器 ;
vu32 BSRR; // 端口位设置/复位寄存器 ;
vu32 BRR; // 端口位复位寄存器 ;
vu32 LCKR; // 端口配置锁定寄存器 ;
} GPIO_TypeDef;
上面的结构体通过 强制指针类型转换得到GPIA的偏移地址
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
主函数如何使用呢?
int main(void)
{
//PA.0链接AB,PA.1连接Clock,PB.0连接Clear
//使得164的QA~QH输出:11000010
//1、设置PA.0推挽输出,PA.1、PB.0推挽输出
GPIOA->CRL = 0x33;
GPIOB->CRL = 0x03;
//2、进行通信
return(1);
}
GPIOA 的寄存器的地址=GPIOA 基地址+寄存器相对 GPIOA 基地址的偏移值, 这个偏移值在上面的寄存器地址映像表中可以查到。
结构体存储的成员他们的地址是连续的, GPIOA 是指向GPIO_TypeDef 类型的指针,又由于GPIO_TypeDef 是结构体,所以自然而然我们就可以算出 GPIOA 指向的结构体成员变量对应地址了:
官方手册 CRL寄存器功能配置图
官方手册 CRH寄存器功能配置图
IDR 和ODR配置
BSSR和其它寄存器可以h查看手册 不列出来了 可以看书(P109页表5-4)
一起学习交流群:QQ群号码:255864236