STM32定时器超详解:从时钟树到影子寄存器,一文吃透定时中断

🚀 我的STM32学习专栏:[点击直达 | 持续更新中]STM32内容讲解

还在用 delay_ms() 阻塞 CPU?软件延时精度差、浪费算力,而 STM32 的硬件定时器能在不占用主循环的情况下,实现从微秒级到近 60 秒的精准定时。本文基于 STM32F103 时钟树与时基单元,把定时器的底层原理、配置流程和避坑要点一次性讲清。
一、定时器能做什么?四大核心功能
STM32 的定时器(TIM)远不止“定时”这么简单,笔记中将其归纳为四大功能:
| 功能 | 说明 | 典型应用 |
|---|---|---|
| 基本定时 | 每隔固定时间产生中断 | 时钟、秒表、任务调度 |
| 输出比较 | 产生 PWM 波形 | 舵机控制、电机调速、LED 呼吸灯 |
| 输入捕获 | 测量外部方波频率/脉宽 | 测速、超声波测距 |
| 编码器接口 | 直接读取正交编码器 | 电机转速与方向反馈 |
二、定时器分类:选对资源不迷路

STM32F103 的定时器分为三类,STM32F103C8T6 仅集成 TIM1~TIM4:
| 类型 | 编号 | 总线 | 核心差异 |
|---|---|---|---|
| 高级定时器 | TIM1、TIM8 | APB2 | 通用功能 + 重复计数器、死区生成、互补输出、刹车输入(专为三相无刷电机设计) |
| 通用定时器 | TIM2~TIM5 | APB1 | 基本功能 + 内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发 |
| 基本定时器 | TIM6、TIM7 | APB1 | 仅支持定时中断 + 主模式触发 DAC |
选型建议:如果只是简单定时中断,用通用定时器即可;如果做电机 PWM,必须上高级定时器。
三、三类定时器框图解析
3.1 基本定时器:最纯粹的"定时中断发生器"
基本定时器仅支持内部时钟(CK_INT)驱动,时钟来自RCC的TIMxCLK(通常为72MHz)。
数据流:RCC → 预分频器PSC → 计数器CNT → 自动重装载ARR → 更新事件/中断
它还有一个特殊技能——主模式触发DAC:通过TRGO信号,在定时器更新时自动触发DAC转换,无需CPU介入,实现硬件级自动运行。

3.2 通用定时器:六边形战士(重点了解)
通用定时器在基本定时器基础上,扩展了两大核心区域:
-
输入捕获通道(IC):测量外部方波频率和脉宽
-
输出比较通道(OC):输出PWM波形驱动电机
时钟源也更加灵活,支持:
-
内部时钟(CK_INT)
-
外部时钟模式1(TIx输入,如TI1FP1)
-
外部时钟模式2(ETR引脚输入)
-
内部触发(ITRx,级联其他定时器)
-
编码器模式
⚠️ 关键限制:对于同一个定时器,输入捕获和输出比较通常不能同时使用同一通道。

3.3 高级定时器:电机控制的终极武器
高级定时器在通用定时器基础上,增加了电机控制必备模块:
-
重复计数器(RCR):实现"每隔N个计数周期才触发一次更新",降低中断频率
-
DTG死区生成电路:防止互补PWM上下管同时导通炸管
-
刹车输入(BKIN):外部紧急信号直接切断PWM输出,保护硬件
-
互补PWM输出:CHx与CHxN成对输出,驱动H桥

四、关键时序:看懂这三张图,定时器不再神秘
5.1 预分频器时序:缓冲机制
预分频器有一个影子寄存器(缓冲器)。当你向PSC写入新值时,并不会立即生效,而是等到下一个更新事件(UEV)时才真正装载。

这意味着:你可以在定时器运行途中修改分频系数,但新参数会在当前计数周期结束后无缝切换,保证波形不突变。
5.2 计数器时序:溢出与更新
当CNT从0计数到ARR(如36),下一个时钟到来时:
-
CNT清零(或向下计数时装载ARR)
-
计数器溢出标志置位
-
更新事件(UEV)产生
-
更新中断标志(UIF)置1,若已使能中断则进入ISR
⚠️ 置1后申请中断,响应后需手动清零。

5.3 影子寄存器的终极意义:预装载(ARPE)
ARR寄存器也有影子寄存器,由ARPE位控制:
| 模式 | ARPE位 | 行为 | 风险 |
|---|---|---|---|
| 无预装 | 0 | 写入ARR立即生效 | 运行中修改可能导致计数器值异常,产生错误中断 |
| 有预装 | 1 | 写入ARR先存到影子寄存器,等更新事件后才生效 | 值的变化与更新事件同步,安全可靠 |


设计意图:影子寄存器实现了寄存器写入与硬件执行的同步隔离。在电机PWM等实时性要求极高的场景中,若ARR修改时机不当,可能导致占空比突变或时钟周期错误,影子寄存器完美解决了这一问题。
五、定时时间计算公式(核心干货)
记住这两条公式,所有定时问题都能算:
计数器时钟频率:
CK_CNT = CK_PSC / (PSC + 1)
定时器溢出频率(中断频率):
CK_CNT_OV = CK_CNT / (ARR + 1)
= CK_PSC / (PSC + 1) / (ARR + 1)
六、时钟树:定时器的"血液"从哪来?
STM32的定时器时钟并非凭空产生,而是来自精心设计的时钟树。

图注:时钟树完整展示了从 HSI/HSE 到 SYSCLK,再经 AHB → APB1/APB2 的分配路径。若 APB1 预分频系数 ≠ 1,则挂接在 APB1 上的 TIM2~TIM7 时钟会 ×2,最终达到 72 MHz;APB2 上的 TIM1/8 同理。
-
APB1 总线最大 36 MHz,TIM2~TIM7 时钟 ×2 → 72 MHz
-
APB2 总线最大 72 MHz,TIM1/8 时钟同样 ×2(若预分频不为 1)→ 72 MHz
结论:在标准库
SystemInit()配置下,所有定时器的基准时钟通常都为 72 MHz。
七、总结
通过本文的系统梳理,我们对 STM32 定时器有了全面的认识:
-
功能定位:定时器不仅是简单的"定时中断发生器",更是集成了输出比较、输入捕获、编码器接口的多功能外设,能满足从基础定时到复杂电机控制的各种需求。
-
分类选择:基本定时器功能纯粹,通用定时器功能全面,高级定时器专为电机控制设计。选型时要根据实际需求匹配资源,避免"大材小用"或"功能不足"。
-
核心原理:理解预分频器、计数器、自动重装载寄存器的协同工作,特别是影子寄存器的缓冲机制,是掌握定时器精确定时的关键。
-
时钟源:定时器的"血液"来自时钟树,标准配置下所有定时器基准时钟通常为 72 MHz,但要注意 APB 预分频系数对定时器时钟的倍增效应。
-
计算公式:掌握 CK_CNT = CK_PSC / (PSC + 1) 和 CK_CNT_OV = CK_CNT / (ARR + 1) 两条核心公式,就能准确计算任意定时需求。
结语:时间,是嵌入式最公平的资源
从简单的LED闪烁,到无刷电机的FOC控制,再到RTOS的滴答时钟——定时器始终是那个默默无闻的"时间裁判"。理解它的时基单元、吃透它的影子寄存器、掌握它的时钟树,你就掌握了在STM32世界里精确丈量时间的能力。
当你下次配置TIM_TimeBaseInitStructure时,希望你看到的不再是一堆枯燥的参数,而是PSC分频器在切割时钟、CNT计数器在稳步前进、ARR影子寄存器在等待那个完美的更新瞬间。
定时器会记住每一个时钟脉冲,就像你的代码会记住每一次精准的中断。
写这篇文章的时候,我把江科大的视频又回顾了一遍,还对照标准库源码和参考手册逐个函数验证,确实比自己单纯听课理解得更深了。如果你也在学STM32,强烈建议你试着把学到的知识点写成博客,教别人是最好的学习方式!
📌 开发环境:Keil5 + STM32F103C8T6最小系统板 + ST-Link
📌 参考资料:江科大STM32入门教程、《STM32F10xxx参考手册》
📌 前置文章:STM32 EXTI 外部中断:函数全解析 + 5 步实战,从时钟到中断一次打通
如果本文对你有帮助,欢迎点赞 👍 收藏 ⭐ !有任何问题欢迎在评论区交流,一起学习进步!
本文配图均来自个人学习笔记以及参考手册,如需转载请注明出处。如有错误,欢迎评论区斧正。

更多推荐


所有评论(0)