【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 秒发送一次数据:

  1. 设置预分频器和 ARR,使 CNT 到达 ARR 需要 1 秒;
  2. 启用中断;
  3. 在中断回调函数中发送数据。

🧩 时钟源配置(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 的影子寄存器。


🔁 中断使用说明

步骤:

  1. CubeMX 勾选 定时器全局中断(Global interrupt)
  2. 使用 HAL_TIM_Base_Start_IT(&htim) 启动中断计时器
  3. 实现回调函数 HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) 处理事件

✅ 总结

STM32 的定时器结构灵活强大,不仅可以用于简单的延时控制,也能完成复杂的工业控制任务。理解定时器的本质"计数器"与其时钟来源、寄存器配置,是灵活使用其各类功能的关键。


相关推荐
国科安芯11 小时前
航天器多路并联大功率电源系统设计与ASP4644均流特性分析
单片机·嵌入式硬件·fpga开发·安全性测试
梁朝辉16 小时前
STM32H750VBT6中ADCINP与INN什么区别
stm32·单片机·嵌入式硬件
崇山峻岭之间18 小时前
单片机无感FOC驱动之ADC
单片机·嵌入式硬件
Ligocious18 小时前
1.点亮一颗小小的LED
单片机·嵌入式硬件
KaifuZeng1 天前
通信与接口协议面试八、CAN通信
单片机·嵌入式硬件·面试·通信与接口协议
智源单片机设计1 天前
基于单片机的直流电机双闭环调速系统设计
单片机·嵌入式硬件
kebidaixu1 天前
两轮车换电 BMS 的模拟前端中颖 SH367306 AFE 芯片详解
stm32
kebidaixu1 天前
两轮车换电 BMS 的模拟前端中颖 SH367306 AFE 芯片调试实录:四个关键问题与解决方案
stm32
wuyk5552 天前
24. C 语言模块化:不是拆几个.c 文件那么简单
c语言·开发语言·stm32·单片机