1.3 TIM 定时器中断 - 实验篇 1

这个实验我们还是做小灯闪烁(间隔 1s), 但是我们不用 HAL_Delay(), 而是使用定时器中断

这里默认你已经看过了前面的实验篇或者会配置 CubeMX 的 cmake 工程, 基础的配置, 比如初始化 PC13 等等这些我不再重复, 这里只提到有关定时器的新的部分


Step 1 - 启用TIM3

Pasted image 20260623011204

为什么用TIM3?, 因为他是一个通用时钟(我们只要用到这个就行了), 这个在我的原理篇中有讲每个时钟分别是什么类型

  • 勾选上 Internal Clock 这个表示使用内部时钟信号(你在时钟树上看到的那个 APB2 Timer clocks), 不是使用内部时钟(Systick)

我们 为了间隔 1s, 需要将 PSC 配置为 7199; ARR 配置为 9999; Counter mode 配置为 up; auto-reload preload 配置为 Enable

  • 给 TIM3 启用中断, 来到 NVIC(中断控制器), 选择启用 Pasted image 20260623011834

Step 2 - 写代码

  • 调用使能定时器中断的函数 HAL_TIM_Base_Start_IT();

我们需要在 main 函数里面的用户代码部分写上使能定时器中断的函数 **HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)**

这里会传入一个参数 &htim3 表示启动的是 TIM3 定时器

Pasted image 20260623014100

  • 编写回调函数

来到stm32f1xx_it.c 的末尾, 我们可以看到这个 TIM3 中断信号(IRQ) 的中断服务函数(ISR)Pasted image 20260623014732 我们转到它的声明和用例, 发现它这个很长, 但是逻辑很清晰: 逐个检查每一种中断标志,哪个事件发生了,就清掉标志、调用对应的回调函数 你看到的那一堆回调,其实对应着定时器能产生的各种不同事件,每种事件配一个回调

我先把它们分类列清楚,再告诉你该用哪个

回调函数 对应事件 什么时候触发
HAL_TIM_PeriodElapsedCallback 更新事件(溢出) 计数器数到 ARR 溢出时
HAL_TIM_IC_CaptureCallback 输入捕获 某通道捕获到外部信号边沿(测频率/脉宽)
HAL_TIM_OC_DelayElapsedCallback 输出比较 CNT 到达比较值时
HAL_TIM_PWM_PulseFinishedCallback PWM 脉冲结束 PWM 一个脉冲完成时
HAL_TIM_TriggerCallback 触发事件 收到触发信号(定时器级联等)
HAL_TIMEx_BreakCallback 刹车输入 高级定时器的刹车保护触发
HAL_TIMEx_CommutCallback 换相事件 电机换相(高级定时器)

可以看到,定时器远不止定时一个用途——它还能做输入捕获、输出比较、PWM、电机控制等。每一种用途对应一种中断事件,也就对应一个回调。 这个 ISR 把所有可能性都写全了,但实际只会执行你启用了的那些

而你要用的就是:HAL_TIM_PeriodElapsedCallback 这个回调函数 Period - 时期;阶段 Elapsed - (时间的)消逝 就是说计数器溢出后周期性地触发中断 Pasted image 20260623015922

继续转跳, 看看这个回调到底是怎么个事Pasted image 20260623020036 哦是我们熟悉的弱函数!

于是我们在 stm32f1xx_it.c 末尾写上这个回调函数Pasted image 20260623020125

看起来大功告成, 锤一锤代码然后烧录上去试试吧!