本文为《零死角玩转 STM32F103—霸道》书籍的知识提取和整理,仅为学习之用。
存储器映射
存储器本身不具有地址信息,它的地址由厂商或用户分配,给已经分配好地址的有特定功能的内存单元取别名的过程称为存储器映射,再分配一地址称为存储器重映射。
在8个Block里面,3个块非常重要。Block0用来设计成内部FLASH,Block1用来设计成内部的RAM,Block2用来设计成片上的外设。
存储器Block0内部区域功能划分
Block0主要设计片内的FLASH。
存储器Block1内部区域功能划分
Block1主要设计片内的SRAM。
存储器Block2内部区域功能划分
Block2主要设计片内的外设,根据外设的总线速度不同,Block被分为了APB和AHB两部分,其中APB又被分为APB1和APB2。
使用C语言进行寄存器简化使用操作(以GPIOB为例)
1.封装总线和外设基地址
/*外设基地址*/
#define PERIPH_BASE ((unsigned int) 0x40000000)
/*总线基地址*/
#define APB1PERIPH_BASE PERIPH_BASE
#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000)
/*GPIO外设基地址*/
#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00)
/*寄存器基地址,以GPIOB为例*/
#define GPIOB_CRL (GPIOB_BASE + 0x00)
#define GPIOB_CRH (GPIOB_BASE + 0x04)
#define GPIOB_IDR (GPIOB_BASE + 0x08)
#define GPIOB_ODR (GPIOB_BASE + 0x0C)
#define GPIOB_BSRR (GPIOB_BASE + 0x10)
#define GPIOB_BRR (GPIOB_BASE + 0x14)
#define GPIOB_LCKR (GPIOB_BASE + 0x18)
/*对单个寄存器进行操作,如GPIOB_BSRR*/
*(unsigned int *)GPIOB_BSRR = (0x01<<(16+0)); /*将第0位输出低电平*/
2.封装寄存器列表
由于GPIOA~GPIOE都各有一组功能相同的寄存器,
只是地址不一样,可以将上述通过基地址用结构体整合起来。
/*使用结构体对GPIO寄存器组的封装*/
typedef unsigned int uint32_t; /*无符号32位变量*/
typedef unsigned short int uint16_t; /*无符号16位变量*/
/*GPIO寄存器列表*/
typedef struct{
/*因为C语言语法规定,结构体变量的存储空间是连续的,其中32位占4个字节,
GPIO寄存器列表的个寄存器也是连续的,所以可以如下编写*/
uint32_t CRL;
uint32_t CRH;
uint32_t IDR;
uint32_t ODR;
uint32_t BSRR;
uint32_t BRR;
uint32_t LCKR;
}GPIO_TypeDef;
3.通过结构体指针访问寄存器
GPIO_TypeDef * GPIOx; /*定义一个GPIO_TypeDef型结构体GPIOx*/
GPIOx = GPIOB_BASE; /*把指针地址设置为宏GPIOB_BASE地址*/
GPIOx->IDR = 0xFFFF; /*设置GPIOB寄存器列表中的IDR寄存器*/
uint32_t temp = GPIOx->IDR; /*读取GPIOB寄存器列表中IDR寄存器的值*/
/*再合并结构体指针*/
#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)
GPIOB->IDR = 0xFFFF; /*设置GPIOB寄存器列表中的IDR寄存器*/
uint32_t temp = GPIOB->IDR; /*读取GPIOB寄存器列表中IDR寄存器的值*/