STM32-定时器
一、定时器概述
1. 软件定时的局限
软件定时通常使用 CPU 死等的方式实现,例如循环执行空指令或等待计数变量变化。
这种方式的问题很明显:
| 问题 | 说明 |
|---|---|
| 延时不精准 | 编译优化、主频变化、中断打断都会影响延时 |
| 浪费 CPU | CPU 在等待期间不能高效处理其他任务 |
| 可维护性差 | 延时时间和代码执行环境强相关 |
因此,在 STM32 中更推荐使用硬件定时器实现精准时基。
2. 定时器定时原理
定时器的核心就是计数器。
定时器使用一个精准时钟作为时基,通过硬件计数的方式实现定时。当计数器达到设定条件后,可以产生更新事件、中断或 DMA 请求。
可以简化理解为:
定时器时钟 -> 预分频器 -> 计数器 -> 溢出/更新事件 -> 中断或触发输出
定时器的优势是:计数过程由硬件完成,CPU 只需要配置参数并处理中断或事件。
3. STM32 定时器分类
STM32 中的定时器可以分为常规定时器、专用定时器和内核定时器。
| 分类 | 典型外设 |
|---|---|
| 基本定时器 | TIM6、TIM7 |
| 通用定时器 | TIM2、TIM3、TIM4、TIM5 等 |
| 高级定时器 | TIM1、TIM8 |
| 专用定时器 | 独立看门狗、窗口看门狗、RTC、低功耗定时器 |
| 内核定时器 | SysTick |
不同 STM32 系列的定时器数量和功能会有差异,实际开发时应参考对应芯片数据手册或开发板开发指南。
4. 基本、通用、高级定时器区别
| 类型 | 主要功能 |
|---|---|
| 基本定时器 | 无输入输出通道,常用作时基 |
| 通用定时器 | 有多路独立通道,可用于输入捕获、输出比较、PWM,也可作时基 |
| 高级定时器 | 具备通用定时器功能,还支持互补输出、死区控制、刹车输入等 |
高级定时器常用于电机控制、数字电源等对 PWM 输出和安全保护要求较高的场景。
二、基本定时器
1. 基本定时器简介
基本定时器常见于 TIM6、TIM7。
主要特性:
-
16 位递增计数器,计数范围
0 ~ 65535 -
16 位预分频器,分频系数
1 ~ 65536 -
可用于触发 DAC
-
在更新事件,也就是计数器溢出时,可产生中断或 DMA 请求
基本定时器没有输入输出通道,因此最常见用途是作为系统中的基础时间片或周期中断源。
2. 基本定时器框图理解
基本定时器主要由三部分组成:
| 模块 | 作用 |
|---|---|
| 时钟源 | 为定时器提供计数时钟 |
| 控制器 | 控制定时器启动、停止、更新事件等 |
| 时基单元 | 包括预分频器、计数器、自动重装载寄存器 |
简化结构:
TIMxCLK -> PSC预分频器 -> CNT计数器 -> ARR自动重装载 -> 更新事件
其中:
-
PSC:预分频寄存器 -
CNT:当前计数器 -
ARR:自动重装载寄存器
3. 计数模式和溢出条件
定时器常见计数模式如下:
| 计数模式 | 溢出或更新条件 |
|---|---|
| 递增计数模式 | CNT == ARR |
| 递减计数模式 | CNT == 0 |
| 中心对齐模式 | CNT == ARR - 1、CNT == 1 |
基本定时器通常使用递增计数模式。
4. 溢出时间计算
定时器溢出时间由定时器时钟、预分频值和自动重装载值决定。
基本公式:
Tout = (PSC + 1) * (ARR + 1) / TIMxCLK
其中:
-
Tout:定时器溢出时间,单位为秒 -
PSC:预分频寄存器的值 -
ARR:自动重装载寄存器的值 -
TIMxCLK:定时器输入时钟频率
如果希望定时器每 500 ms 产生一次更新中断,就需要根据 TIMxCLK 反推合适的 PSC 和 ARR。
5. 基本定时器中断配置步骤
使用 HAL 库配置基本定时器中断,可以按以下流程理解:
-
配置定时器基础工作参数:
HAL_TIM_Base_Init() -
完成 MSP 底层初始化:
HAL_TIM_Base_MspInit() -
使能更新中断并启动计数器:
HAL_TIM_Base_Start_IT() -
设置中断优先级并使能中断:
HAL_NVIC_SetPriority()、HAL_NVIC_EnableIRQ() -
编写中断服务函数:
TIMx_IRQHandler(),并调用HAL_TIM_IRQHandler() -
编写定时器更新中断回调函数:
HAL_TIM_PeriodElapsedCallback()
中断调用链可以理解为:
TIMx_IRQHandler() -> HAL_TIM_IRQHandler() -> HAL_TIM_PeriodElapsedCallback()
三、通用定时器
1. 通用定时器简介
以 STM32F1 为例,通用定时器包括 TIM2、TIM3、TIM4、TIM5。
主要特性:
-
16 位递增、递减、中心对齐计数器,计数范围
0 ~ 65535 -
16 位预分频器,分频系数
1 ~ 65536 -
可用于触发 DAC、ADC
-
在更新事件、触发事件、输入捕获、输出比较时可产生中断或 DMA 请求
-
具备 4 个独立通道
-
支持输入捕获、输出比较、PWM、单脉冲模式
-
支持外部信号控制定时器
-
支持多个定时器互连
-
支持编码器和霍尔传感器接口
相比基本定时器,通用定时器的重点是“通道”。有了通道,定时器就可以和外部 IO 信号产生联系。
2. 通用定时器框图理解
通用定时器可以分为以下功能模块:
| 模块 | 作用 |
|---|---|
| 时钟源 | 决定计数器计数节拍 |
| 控制器 | 控制定时器运行模式 |
| 时基单元 | 完成分频、计数、自动重装载 |
| 输入捕获 | 捕获外部输入信号的时间点 |
| 捕获/比较公共部分 | 连接输入捕获和输出比较 |
| 输出比较 | 根据比较值控制输出状态 |
通用定时器既可以用作普通定时中断,也可以用来产生 PWM、测量脉宽、统计外部脉冲等。
3. 计数器时钟源
通用定时器常见时钟源包括:
| 时钟源 | 说明 | 关键配置 |
|---|---|---|
内部时钟 CK_INT |
来自外设总线 APB 提供的时钟 | TIMx_SMCR.SMS = 000 |
| 外部时钟模式 1 | 来自定时器通道 1 或通道 2 引脚信号 | TIMx_SMCR.SMS = 111 |
| 外部时钟模式 2 | 来自可复用为 TIMx_ETR 的 IO 引脚 |
TIMx_SMCR.ECE = 1 |
内部触发输入 ITRx |
用于与其他通用/高级定时器级联 | 参考芯片参考手册 |
外部时钟和内部触发输入使定时器可以参与更复杂的同步控制,例如定时器级联、外部脉冲计数等。
四、通用定时器 PWM 输出
1. 输出比较与 PWM 原理
PWM 输出依赖输出比较功能。
定时器计数器 CNT 按时基不断变化,捕获/比较寄存器 CCRx 保存比较值。当 CNT 与 CCRx 的关系满足某种条件时,输出电平发生变化,从而形成 PWM 波形。
PWM 的两个关键参数:
| 参数 | 决定因素 |
|---|---|
| 周期或频率 | 由 ARR 决定 |
| 占空比 | 由 CCRx 决定 |
常见计算关系:
PWM频率 = TIMxCLK / ((PSC + 1) * (ARR + 1))
占空比 = CCRx / (ARR + 1)
2. PWM 模式
通用定时器常见 PWM 模式包括:
| 模式 | 理解方式 |
|---|---|
| PWM 模式 1 | 在不同计数区间输出有效/无效电平 |
| PWM 模式 2 | 与模式 1 的有效电平区间相反 |
实际输出电平还与极性配置有关。配置 PWM 时,除了模式本身,还需要关注通道极性、预装载、GPIO 复用等参数。
3. PWM 输出配置步骤
使用 HAL 库配置 PWM 输出时,典型流程如下:
-
配置定时器基础工作参数:
HAL_TIM_PWM_Init() -
完成 PWM MSP 初始化:
HAL_TIM_PWM_MspInit() -
配置 PWM 模式、比较值等:
HAL_TIM_PWM_ConfigChannel() -
使能输出并启动计数器:
HAL_TIM_PWM_Start() -
根据需要修改比较值控制占空比:
__HAL_TIM_SET_COMPARE() -
根据需要使能通道预装载:
__HAL_TIM_ENABLE_OCxPRELOAD()
如果 PWM 引脚没有输出,优先检查 GPIO 是否配置为正确的复用功能。
五、通用定时器输入捕获
1. 输入捕获原理
输入捕获用于记录外部信号边沿到来时的计数器值。
当配置好的边沿到来时,当前 CNT 的值会被锁存到对应的 CCRx 寄存器中。通过比较两次捕获值,就可以计算周期、频率或脉宽。
测量高电平脉宽时,可以理解为:
高电平计数个数 = 溢出次数 * (ARR + 1) + 捕获差值
高电平期间的计数个数可以表示为:
高电平期间计数个数 = N * (ARR + 1) + CCRx2
其中 N 表示高电平期间发生的定时器溢出次数。
2. 输入捕获配置步骤
使用 HAL 库配置输入捕获时,典型流程如下:
-
配置定时器基础工作参数:
HAL_TIM_IC_Init() -
完成输入捕获 MSP 初始化:
HAL_TIM_IC_MspInit() -
配置输入通道映射、捕获边沿等:
HAL_TIM_IC_ConfigChannel() -
设置中断优先级并使能中断:
HAL_NVIC_SetPriority()、HAL_NVIC_EnableIRQ() -
使能定时器更新中断:
__HAL_TIM_ENABLE_IT() -
使能捕获、捕获中断和计数器:
HAL_TIM_IC_Start_IT() -
编写中断服务函数:
TIMx_IRQHandler(),并调用HAL_TIM_IRQHandler() -
编写更新中断和捕获回调函数:
HAL_TIM_PeriodElapsedCallback()、HAL_TIM_IC_CaptureCallback()
输入捕获常用于测量按键脉宽、外部 PWM 周期、超声波模块回波时间等。
六、通用定时器脉冲计数
通用定时器也可以使用外部输入信号作为计数时钟,实现脉冲计数。
1. 脉冲计数原理
当定时器使用外部时钟模式时,外部引脚输入的脉冲会驱动计数器递增。此时定时器不再主要依赖内部时钟计时,而是用于统计外部脉冲个数。
典型用途:
-
统计外部方波脉冲数量
-
测量转速传感器脉冲
-
统计编码器相关输入信号
2. 脉冲计数配置步骤
使用 HAL 库配置脉冲计数时,典型流程如下:
-
配置定时器基础工作参数:
HAL_TIM_IC_Init() -
完成输入捕获 MSP 初始化:
HAL_TIM_IC_MspInit() -
配置定时器从模式:
HAL_TIM_SlaveConfigSynchro() -
使能输入捕获并启动计数器:
HAL_TIM_IC_Start() -
获取计数器值:
__HAL_TIM_GET_COUNTER() -
设置计数器值:
__HAL_TIM_SET_COUNTER()
脉冲计数配置的重点是选择正确的外部时钟源、输入通道和从模式。
七、高级定时器
1. 高级定时器简介
高级定时器常见于 TIM1、TIM8。
主要特性:
-
16 位递增、递减、中心对齐计数器
-
16 位预分频器
-
可用于触发 DAC、ADC
-
支持更新事件、触发事件、输入捕获、输出比较中断或 DMA 请求
-
具备 4 个独立通道
-
支持输入捕获、输出比较、PWM、单脉冲模式
-
支持外部信号控制定时器和定时器互连
-
支持编码器和霍尔传感器接口
-
支持重复计数器
-
支持带死区时间控制的互补输出
-
支持断路输入,用于输出安全保护
高级定时器比通用定时器更适合复杂 PWM 控制,尤其是电机驱动和功率控制场景。
2. 高级定时器框图重点
高级定时器在通用定时器基础上,重点增加了:
| 模块 | 作用 |
|---|---|
| 重复计数器 | 控制多次溢出后才产生更新事件 |
| 互补输出 | 输出互补 PWM 信号 |
| 死区控制 | 防止上下桥臂同时导通 |
| 刹车功能 | 异常时快速关闭或切换输出状态 |
八、重复计数器与指定个数 PWM
重复计数器用于控制更新事件的产生频率。
重复计数器的关键结论:
计数器每次上溢或下溢都会使重复计数器减 1,减到 0 时产生更新事件。
如果设置 RCR = N,则更新事件会在 N + 1 次溢出后产生。
如果需要输出指定个数的 PWM,可以按以下思路理解:
-
配置边沿对齐模式输出 PWM。
-
如果要输出
N个 PWM,则把N - 1写入重复计数器RCR。 -
在更新中断中关闭计数器。
配置步骤
使用 HAL 库配置高级定时器输出指定个数 PWM 时,典型流程如下:
-
配置定时器基础工作参数:
HAL_TIM_PWM_Init() -
完成 PWM MSP 初始化:
HAL_TIM_PWM_MspInit() -
配置 PWM 模式、比较值等:
HAL_TIM_PWM_ConfigChannel() -
设置中断优先级并使能中断:
HAL_NVIC_SetPriority()、HAL_NVIC_EnableIRQ() -
使能定时器更新中断:
__HAL_TIM_ENABLE_IT() -
使能输出、主输出和计数器:
HAL_TIM_PWM_Start() -
编写中断服务函数:
TIMx_IRQHandler(),并调用HAL_TIM_IRQHandler() -
编写更新中断回调函数:
HAL_TIM_PeriodElapsedCallback()
九、高级定时器输出比较模式
输出比较模式可以根据 CNT 和 CCRx 的比较结果改变通道输出。
输出比较模式的关键结论:
PWM 波周期或频率由 ARR 决定,占空比固定 50%,相位由 CCRx 决定。
配置步骤
使用 HAL 库配置输出比较模式时,典型流程如下:
-
配置定时器基础工作参数:
HAL_TIM_OC_Init() -
完成输出比较 MSP 初始化:
HAL_TIM_OC_MspInit() -
配置输出比较模式:
HAL_TIM_OC_ConfigChannel() -
使能通道预装载:
__HAL_TIM_ENABLE_OCxPRELOAD() -
使能输出、主输出和计数器:
HAL_TIM_OC_Start() -
根据需要修改捕获/比较寄存器值:
__HAL_TIM_SET_COMPARE()
十、高级定时器互补输出、死区与刹车
1. 互补输出与死区控制
互补输出常用于半桥、全桥、电机驱动等场景。由于功率器件存在开关延迟,如果上下桥臂同时导通,会造成短路风险,因此需要加入死区时间。
死区控制的作用是:在互补信号切换时人为插入一小段两个输出都无效的时间,避免上下管直通。
2. 刹车功能
刹车功能也叫断路功能,用于在异常输入出现时,将定时器输出切换到安全状态。
使能刹车功能的关键点:
-
将
TIMx_BDTR的BKE位置 1。 -
刹车输入信号极性由
BKP位设置。 -
输出状态受
MOE、OSSI、OSSR、OISx、OISxN、CCxE、CCxNE等位影响。 -
无论何时,
OCx和OCxN输出都不能同时处在有效电平。
发生刹车后,可能出现以下结果:
-
MOE位被清零,OCx和OCxN输出进入无效、空闲或复位状态。 -
互补输出状态由相关控制位和参考手册定义决定。
-
BIF位置 1,如果使能BIE,会产生刹车中断;如果使能TDE,会产生 DMA 请求。 -
如果
AOE位置 1,在下一个更新事件UEV时,MOE会被自动置 1。
3. 互补输出带死区控制配置步骤
使用 HAL 库配置互补输出和死区控制时,典型流程如下:
-
配置定时器基础工作参数:
HAL_TIM_PWM_Init() -
完成 PWM MSP 初始化:
HAL_TIM_PWM_MspInit() -
配置 PWM 模式、比较值等:
HAL_TIM_PWM_ConfigChannel() -
配置刹车功能、死区时间等:
HAL_TIMEx_ConfigBreakDeadTime() -
使能输出、主输出和计数器:
HAL_TIM_PWM_Start() -
使能互补输出、主输出和计数器:
HAL_TIMEx_PWMN_Start()
十一、高级定时器 PWM 输入模式
PWM 输入模式可以用于测量外部 PWM 信号的频率、周期和占空比。
基本思路是使用两个捕获通道配合:
-
一个通道捕获周期相关边沿。
-
另一个通道捕获占空比相关边沿。
-
再通过捕获值计算频率和占空比。
配置步骤
使用 HAL 库配置 PWM 输入模式时,典型流程如下:
-
配置定时器基础工作参数:
HAL_TIM_IC_Init() -
完成输入捕获 MSP 初始化:
HAL_TIM_IC_MspInit() -
配置 IC1/IC2 映射、捕获边沿等:
HAL_TIM_IC_ConfigChannel() -
配置从模式、触发源等:
HAL_TIM_SlaveConfigSynchro() -
设置中断优先级并使能中断:
HAL_NVIC_SetPriority()、HAL_NVIC_EnableIRQ() -
使能捕获、更新/捕获中断和计数器:
HAL_TIM_IC_Start_IT()、HAL_TIM_IC_Start() -
编写中断服务函数:
TIMx_IRQHandler(),并调用HAL_TIM_IRQHandler() -
编写捕获回调函数:
HAL_TIM_IC_CaptureCallback()
更多推荐

所有评论(0)