1,定时器概述(了解)
1.1,软件定时原理
使用纯软件(CPU死等)的方式实现定时(延时)功能
void delay_us(uint32_t us)
{
us *= 72;
while(us--);
}
缺点:
1,延时不精准
2,CPU死等
1.2,定时器定时原理
使用精准的时基,通过硬件的方式,实现定时功能
定时器核心就是计数器
1.3,STM32定时器分类
1.4,STM32定时器特性表
F1
H7
1.5,STM32基本、通用、高级定时器的功能整体区别
定时器类型 | 主要功能 |
---|---|
基本定时器 | 没有输入输出通道,常用作时基,即定时功能 |
通用定时器 | 具有多路独立通道,可用于输入捕获/输出比较,也可用作时基 |
高级定时器 | 除具备通用定时器所有功能外,还具备带死区控制的互补信号输出、刹车输入等功能(可用于电机控制、数字电源设计等) |
2,基本定时器(掌握)
2.1,基本定时器简介(了解)
- 基本定时器:TIM6/TIM7
- 主要特征:
- 16位递增计数器(计数值:0~65535)~
- 16位预分频器(分频系数:1~65536)
- 可用于触发DAC
- 在更新事件(计数器溢出)时,会产生中断/DMA请求
2.2,基本定时器框图(熟悉)
- 时钟源来自RCC,来自于内部时钟(基本定时器的时钟只允许来自于内部时钟)
- 时钟源->控制器->预分频器(PSC):分频系数:1~65535
- 设置的频率为CK_CNT:该频率为CNT计数器真正工作的频率
- 每来一个CK_CNT时钟,CNT计数器+1
- 当加到计数器溢出为止:(溢出条件:CNT == ARR(影子))
- ARR为自动重载寄存器,看图该寄存器后面还有一个影子,该影子称为这个寄存器的影子寄存器
- 影子寄存器是实际起作用的寄存器,不可直接访问
- ARR非影子寄存器的作用:起到了缓冲的作用
- 我们写入ARR的值不能马上起作用,必须要写入影子寄存器中才能适用,
- 需要触发事件才能将ARR的值写入影子寄存器中
- 当溢出条件满足后,发生两个动作:事件(U)、中断和DMA输出(UI)
- 事件(U)是默认产生的,也可以设置不产生
- 中断和DMA输出(UI)默认不产生,也可以设置产生
- 也可以通过UG位来产生软件更新事件
- 当产生更新事件:会预装载寄存器的值加载到对应影子寄存器
- 其中ARPE位决定ARR是否具有缓冲作用
- 如果设置具有缓冲作用,它不是直接生效的,还需要等到更新事件产生,将值转移到它的影子寄存器中,这个时候真正起作用
- 如果设置无缓冲作用,当设置寄存器的值时,它会马上转移到影子寄存器中,直接生效
- TRGO什么时候产生:当触发溢出时候就会产生
- 其中的APB1的时钟频率为:45MHz
- APB2的时钟频率为:90MHz
- 那是否说明挂载在APB2的TIM1的最大时钟频率为90MHz,TIM2的最大频率为:45MHz?
- 实际上不完全是!!
- 还需要根据APB1的预分频系数和APB2的预分频系数
2.3,定时器计数模式及溢出条件(熟悉)
计数器模式 | 溢出条件 |
---|---|
递增计数模式 | CNT==ARR |
递减计数模式 | CNT==0 |
中心对齐模式 | CNT == ARR-1、CNT == 1 |
递增计数模式实例说明
PSC=1
ARR=36
我们假设PSC=1:代表2分频
ARR=36
- CNT_EN的使能位,=0的时候不工作,=1的时候工作
- CK_CNT为定时器的计数时钟,==CNT==经过分频后的时钟
- 因为分频系数为2,所以每来两个==CK_PSC==时钟,==CK_CNT==就计数一次
- 当计数器寄存器+到36就溢出,就生成溢出事件(上溢)
- 当溢出器溢出产生更新事件
- 更新中断标志位置1(硬件置1)
- 但是它不一定产生中断,但它会硬件置1
- 如果配置产生中断,那么它就会产生中断,会在中断服务函数中把中断标志位清零
递减计数模式实例说明
PSC=1
ARR=36
中心对齐模式实例说明
PSC = 0
ARR = 6
2.4,定时器中断实验相关寄存器(了解)
TIM6和TIM7控制寄存器1(TIMx_CR1)
用于设置ARR寄存器是否具有缓冲,使能/关闭计数器
TIM6和TIM7 DMA/中断使能寄存器(TIMx_DIER)
用于使能更新中断
TIM6 和TIM7 状态寄存器(TIMx_SR)
用于判断是否发生了更新中断,由硬件置1,软件清零
TIM6 和TIM7 计数器(TIMx_CNT)
计数器实时数值,可用于设置计时器初始值,范围:0~65535
TIM6 和TIM7 预分频器(TIMx_PSC)
用于设置预分频系数,范围:0~65535,实际预分频系数等于PSC+1
TIM6 和TIM7 自动重装载寄存器(TIMx_ARR)
用于设置自动重装载值,范围:0~65535
2.5,定时器溢出时间计算方法(掌握)
其中$F_t$是没有经过分频的时钟源频率
2.6,定时器中断实验配置步骤(掌握)
步骤 | 说明 |
---|---|
1,配置定时器基础工作参数 | HAL_TIM_Base_Init() |
2,定时器基础MSP初始化 | HAL_TIM_Base_MspInit() 配置NVIC、CLOCK等 |
3,使能更新中断并启动计数器 | HAL_TIM_Base_Start_IT() |
4,设置优先级,使能中断 | HAL_NVIC_SetPriority()、 HAL_NVIC_EnableIRQ() |
5,编写中断服务函数 | TIMx_IRQHandler()等 à HAL_TIM_IRQHandler() |
6,编写定时器更新中断回调函数 | HAL_TIM_PeriodElapsedCallback() |
相关HAL库函数介绍
函数 | 主要寄存器 | 主要功能 |
---|---|---|
HAL_TIM_Base_Init() | CR1、ARR、PSC | 初始化定时器基础参数 |
HAL_TIM_Base_MspInit() | 无 | 存放NVIC、CLOCK、GPIO初始化代码 |
HAL_TIM_Base_Start_IT() | DIER、CR1 | 使能更新中断并启动计数器 |
HAL_TIM_IRQHandler() | SR | 定时器中断处理公用函数,处理各种中断 |
HAL_TIM_PeriodElapsedCallback() | 无 | 定时器更新中断回调函数,由用户重定义 |
关键结构体介绍
typedef struct
{
TIM_TypeDef *Instance; /* 外设寄存器基地址 */
TIM_Base_InitTypeDef Init; /* 定时器初始化结构体*/
...
} TIM_HandleTypeDef;
typedef struct
{
uint32_t Prescaler; /* 预分频系数 */
uint32_t CounterMode; /* 计数模式 */
uint32_t Period; /* 自动重载值 ARR */
uint32_t ClockDivision; /* 时钟分频因子 */
uint32_t RepetitionCounter; /* 重复计数器寄存器的值 */
uint32_t AutoReloadPreload; /* 自动重载预装载使能 */
} TIM_Base_InitTypeDef;
2.7,编程实战:定时器中断实验(掌握)
使用定时器6,实现500ms定时器更新中断,在中断里翻转LED0
$F_t=60MHz$
$ARR=4999$
$PSC=5999$
3,通用定时器(掌握)
3.1,通用定时器简介(了解)
- 通用定时器:TIM2/TIM3 /TIM4 /TIM5
- 主要特性
- 16位递增、递减、中心对齐计数器(计数值:0~65535)~
- 16位预分频器(分频系数:1~65536)
- 可用于触发DAC、ADC
- 在更新事件、触发事件、输入捕获、输出比较时,会产生中断/DMA请求
- 4个独立通道,可用于:输入捕获、输出比较、输出PWM、单脉冲模式
- 使用外部信号控制定时器且可实现多个定时器互连的同步电路
- 支持编码器和霍尔传感器电路等
3.2,通用定时器框图(熟悉)
①时钟源
②控制器
③时基单元
④输入捕获
⑤捕获/比较(公共)
⑥输出比较
- 这里通用定时器框图分为六部分来介绍
- 第1部分,时钟源部分,只能来自于内部时钟(APB)
- 其中时钟源有四类
- 第一类:内部时钟(APB)
- 内部触发输入时钟部分
- 来自于IO外部时钟2(TIMx_ETR)
- 来自于外部时钟1(TI1F_ED、TI1FP1、TI1FP2){及定时器通道1(TIMx_CH1)、定时器通道2(TIMx_CH2)}
- 控制器部分,我们可以看到这个控制器比通用定时器多了,可以触发DAC/ADC以己到其他定时器
- 第4部分的输入捕获会与第5部分的共同使用
- 使用第六部分会和第5部分共同使用
- 外部时钟通过IO口复用TIMx_CH1,进入异或门,进入输入滤波器和边缘检测器,得到TI1FP1、TI2FP2
- IC1预分频器,产生捕获事件,进入捕获/比较1寄存器
- 第六部分:
- 程序员会往捕获/比较1寄存器写比较值