下面是个人在《STM32库开发实践指南》这本书的学习过程中,从中提炼的要点笔记,以及自己的一些理解,以便后期复习回顾。由于本科阶段个人能力有限,如果以下篇幅中论述有误,欢迎大家提醒小弟。
STM32是由Cortex-M3内核(CPU)、片上外设、内部总线等组成的单片微型计算机,其芯片结构如下:
Corten-M3是由ARM公司设计的一款处理器架构,片上外设等部件是由芯片生产商设计的,所以不同的生产商设计的单片机的硬件结构不尽相同(内核都是Cortex-M3),为了解决不同硬件平台的软件编程上的差异,ARM公司建立了CMSIS软件抽象层标准,相当于操作系统的设备无关层软件。
Cortex-M3内核文件:
ST库文件:
misc.c
用于提供NVIC(中断向量控制器)的访问函数。用户程序文件:
同51一样,Cortex-M3将存储器地址与外设地址一起编址,其地址总线宽度为32bit,有4GB的寻址空间,其地址分配情况如下:
其中0x40000000-0x5FFFFFFF的地址用于指向STM32片上外设,stm32f10x.h记录了这些寄存器的地址情况。
#define PERIPH_BASE ((uint32_t)0x40000000) //外设基址
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) //APB2总线基址
#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800) //GPIOA外设基址
外设基址 PERIPH: Cortex-M3分配给生产厂商片上外设地址,512MB
总线外设基址 APB1, APB2, AHB: 在STM32中将不同速率的片上外设挂载在不同的总线上,其将PERIPH的地址空间划分为了三部分:
总线 | 地址空间 | 大小 |
---|---|---|
APB1 | 4000 0000 H - 4000 FFFF H | 64KB |
APB2 | 4001 0000 H - 4001 7FFF H | 28KB |
AHB | 4001 8000 H - 5FFF FFFF H | 512MB - 98KB |
寄存器组基址: 由于一条总线可以挂载多个外设,所以将总线地址空间又划分为多个寄存器地址空间。
以上为一个寄存器地址空间,每个寄存器地址空间大小为32bit,在STM32中将多个相关的寄存器划分为一个寄存器组,地址偏移0x04是先对与其寄存器组基址(GPIOx_BASH)的。在stm32f10x.h
中将寄存器组封装为一个结构体,以便于访问:
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;
STM32的时钟系统比较复杂,需要经过倍频、分频以及一系列外设时钟的开关,其原因如下:
STM32为每个外设的时钟输出都设置了开关,这样可以有效的降低系统功耗。
STM32的系统时钟 SYSCLK 的来源有四种方式:外部时钟信号直接获取(HSE, LSE)、内部时钟信号直接获取(HSI, LSI)、外部或内部信号锁相环获取(PLLCK),下图的 SW 开关就是用于选择时钟信号的获取方式的。
经过一系列的分频、倍频之后得到几个与我们开发密切相关的时钟:
通过初始化配置结构体实现如,配置步骤如下:
xxx_InitTypeDef
类型初始化结构体;xxx_Init()
函数向寄存器写入参数。GPIO_SetData()
,USART_SendData()
;GPIO_ReadOutputDataBit()
,GPIO_ReadInputDataBit()
,USART_ReceiveData()
。STM32通过事件中断来反应寄存器的变化,并在中断服务函数中处理这事件,由于多个函数可能共享一个中断服务函数,故需要对外设的SR进行检测与清除:
xxx_GetFlagStatus()
,xxx_GetITStatus()
,当屏蔽中断使后者无法检测;xxx_ClearFlag()
,xxx_ClearITPendingBit()
,在处理中断时使用后者,处理标志位时使用前者。