🚀 我的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),下一个时钟到来时:

  1. CNT清零(或向下计数时装载ARR)

  2. 计数器溢出标志置位

  3. 更新事件(UEV)产生

  4. 更新中断标志(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 时钟 ×272 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 步实战,从时钟到中断一次打通

如果本文对你有帮助,欢迎点赞 👍 收藏 ⭐ !有任何问题欢迎在评论区交流,一起学习进步!

本文配图均来自个人学习笔记以及参考手册,如需转载请注明出处。如有错误,欢迎评论区斧正。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐