【STM32】定时器
STM32 定时器详解笔记
📌 定时器的本质:计数器!
STM32 中的定时器本质就是 一个可编程的计数器。它通过对时钟脉冲进行计数,从而实现精确的时间控制。
🧩 定时器的功能
定时器不仅能“计时”,还可完成丰富的功能:
- ⏱️ 精确计时/延时
- ⏹️ 捕获脉冲宽度(输入捕获)
- 🧮 计算 PWM 占空比
- 📤 输出 PWM 波形(输出比较)
- 🔁 周期性中断事件触发
- ⚙️ 驱动 DAC、编码器接口等
🧭 定时器的分类
定时器类型 | 特点 |
---|---|
高级定时器 | 支持互补输出、死区时间、刹车输入等,适用于电机控制(如 TIM1、TIM8) |
通用定时器 | 功能全面,适用于大多数计时、PWM、输入捕获等功能(如 TIM2~TIM5) |
基本定时器 | 仅用于简单计时、中断或 DAC 触发(如 TIM6、TIM7) |
⏳ STM32 如何实现“计时”?
✔️ 原理描述
以一个恒定频率的输入方波为基础,每当检测到一个脉冲(如上升沿),计数器的值加 1:
- 若方波频率为 100Hz,则 1 秒内会产生 100 个脉冲;
- 当计数器计满 100,就表示时间过去了 1 秒。
❓ 那么这个“方波”信号从哪来?
STM32 的定时器时钟源来自系统时钟(经过配置后从 APB 总线 分发)。
- 通用/基本定时器:挂载在 APB1
- 高级定时器:挂载在 APB2
举例:当系统设置时钟为 72 MHz
,则定时器每秒收到 72M
个脉冲。
⚠️ 寄存器限制与预分频器的作用
- STM32 大多数定时器计数器为 16 位,最大值为 65535;
- 72MHz 频率下,计满一次仅需约
0.00091s
; - 想要计较长时间怎么办?
🧱 引入预分频器(Prescaler)
预分频器本质也是一个计数器,作用是对输入时钟进行分频:
- 设置为
0
表示 1 分频(不分频) - 设置为
1
表示 2 分频 - 设置为
n-1
表示 n 分频
📌 预分频器的寄存器也是 16 位,最大分频可达 65536
倍!
例如:
72 MHz ÷ 65536 ÷ 65536 ≈ 0.00023 Hz
,计数周期最长可达 约 59.65 秒
🔁 串联计时器
多个定时器还可以通过主从机制实现更长时间的计时(如 TIM6 作为 TIM7 的时钟源)。
📤 周期性事件与中断:自动重装载寄存器(ARR)
- 用于设置计数器的上限值;
- 当 CNT 计满并等于 ARR,触发一次 更新事件(Update Event);
- 此时 CNT 被重置为 0,若开启中断,也将触发一次 中断服务函数。
🧠 示例用途
每 1 秒发送一次数据:
- 设置预分频器和 ARR,使 CNT 到达 ARR 需要 1 秒;
- 启用中断;
- 在中断回调函数中发送数据。
🧩 时钟源配置(CubeMX 中的 Internal Clock
)
在 CubeMX 中配置定时器时,会看到 Clock Source = Internal Clock
:
- 意思是使用 来自内部时钟树 的时钟作为定时器输入;
- 和你选择的 系统主时钟源(如 HSE 通过 PLL 放大) 是有关联的;
- 实际上,“internal”不是指定一个固定频率,而是来自你配置的时钟树的 APB 时钟。
🔧 常用 HAL 函数与宏定义
🔹 基础控制
函数 | 功能 |
---|---|
HAL_TIM_Base_Start(&htim) | 启动定时器基础功能(不启用中断) |
HAL_TIM_Base_Start_IT(&htim) | 启动定时器并启用更新中断 |
__HAL_TIM_GET_COUNTER(&htim) | 获取当前计数器值 |
HAL_TIM_SET_COUNTER(&htim, val) | 设置 CNT 的初始值 |
__HAL_TIM_GET_AUTORELOAD(&htim) | 获取自动重装载值 |
__HAL_TIM_SET_PRESCALER(&htim, val) | 设置预分频值 |
🧠 宏函数命名特点
带有 __HAL_
开头、全部大写的函数,一般为底层直接寄存器操作的宏定义。
🧱 影子寄存器机制
💡 为什么我们设置的值不会立刻生效?
定时器的 预分频器 PSC 和 自动重装载寄存器 ARR 都存在影子寄存器(Shadow Register):
- 设置的新值,不会立即生效;
- 只有在 CNT 发生更新事件(达到 ARR)后,新值才会被写入影子寄存器并应用;
- 保证修改参数过程中,不影响正在运行的计数周期。
📌 CubeMX 中可设置是否启用 ARR 的影子寄存器。
🔁 中断使用说明
步骤:
- CubeMX 勾选 定时器全局中断(Global interrupt)
- 使用
HAL_TIM_Base_Start_IT(&htim)
启动中断计时器 - 实现回调函数
HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
处理事件
✅ 总结
STM32 的定时器结构灵活强大,不仅可以用于简单的延时控制,也能完成复杂的工业控制任务。理解定时器的本质“计数器”与其时钟来源、寄存器配置,是灵活使用其各类功能的关键。