SMARTWATCH 学习手册有 C 基础 · 嵌入式从零开始
嵌入式拓展 / 02

定时器:让硬件计数、定时和输出脉冲

已经知道时钟从哪里来,接下来让一个计数器按这个节奏前进。数够指定次数就通知程序,数到指定位置就改变引脚,也可以在外部边沿到来时记下当前计数。

它在当前手表里用在哪里?

主控用 TIM6 提供 HAL 毫秒计时。传感器水位通知与麦克风连续采集沿前文实现即可。本篇补充定时器在其他控制、测量项目中的常用方法,完成后可以继续系统保护拓展,或回到 裸机逻辑综合。

第 1 节 · 一个计数器,怎样得到指定时间?

定时器输入时钟每跳一拍,内部计数器就按配置增加。计数前先经过预分频,可以让它每隔几拍才增加一次。源码中常见的 PSC 是预分频寄存器,CNT 是当前计数,ARR 是计数终点对应的自动重装载值。

例如输入时钟为 160 MHz,PSC 写 159,表示每 160 拍产生一次计数,计数频率变为 1 MHz,每格 1 微秒。ARR 写 999,计数依次经过 0~999,共 1000 格,约每 1 毫秒产生一次更新事件,然后从零开始。

来源时钟经过预分频推动计数,数到终点触发更新,与比较值相遇可改变输出
先确定计数节奏,再决定数到哪里产生动作。

对于这里的向上计数例子,更新频率=输入时钟÷(PSC+1)÷(ARR+1)。两个加一来自寄存器从零开始表示数量。其他计数方式要按对应规则计算;定时器输入时钟也要沿时钟树确定,不能默认等于 CPU 主频。

第 2 节 · 数够以后,怎样让程序知道?

打开更新中断,计数到终点时,处理器进入定时器中断,HAL 再调用 HAL_TIM_PeriodElapsedCallback()。回调参数告诉程序哪一个定时器产生事件;回调适合设置短小通知,后续主循环完成具体工作。

当前项目的 TIM6 先把计数节奏配置为每格 1 微秒,再数 1000 格,形成 1 毫秒更新。main.c 的周期回调识别 TIM6,调用 HAL_IncTick() 增加 HAL 毫秒计数;HAL_GetTick、延时与超时判断依靠它前进。

为什么中断里调用 HAL_Delay 可能一直出不来?

HAL_Delay 等待毫秒计数变化。如果当前中断的抢占优先级高于或等于 TIM6,TIM6 不能打断它;当前中断又在等 TIM6 更新计数,于是双方互相等,延时无法结束。当前工程的 TIM6 优先级数值为 15,许多外设中断数值更小,抢占级别更高。

若希望计时中断能打断当前中断,需要更高的抢占优先级,在 Cortex-M 上通常表现为更小的数值;只调整子优先级不能解决抢占问题。教学中优先把需要等待的工作交给主循环,回调设置标志后就返回。完整优先级规则可回看 中断章节。

第 3 节 · 同一个计数器,怎样让引脚按比例高低变化?

再增加一个比较值 CCR。对于向上计数、有效高电平的 PWM mode 1,可以理解为:计数小于比较值时输出高电平,到达比较值后输出低电平,下一轮又重复。这就是脉宽调制,缩写 PWM。

仍以一轮 1000 格为例,比较值为 250,高电平约占 250 格,低电平占其余 750 格,占空比约 25%。改变比较值能改变一轮内高电平的比例;改变分频或终点则会改变周期。

改变计数终点和比较比例

向上计数、边沿对齐、PWM mode 1 的简化示意。波形横向只表示比例,实际频率看计算结果。

独立实验可在支持通道输出的定时器上配置,例如生成 TIM2 及其通道 1 的代码,选有对应复用功能的空闲实验引脚。包含 tim.h 后,htim2 是生成的管理对象;HAL_TIM_PWM_Start 启动通道,__HAL_TIM_SET_COMPARE 修改比较值:

if (HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1) == HAL_OK) {
    __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 250);
}

这是独立通道实验;TIM6 是基本定时器,没有可供这段代码使用的输出通道。输出驱动能力要符合负载需要,电机等负载需配套驱动电路。用分析仪测周期和高电平宽度,才能确认实际配置。

第 4 节 · 反过来,能测量外面送来的周期吗?

可以。输入捕获在引脚指定边沿到来时,把当前计数值锁存到捕获寄存器。连续两次同类边沿之间的计数差,就是周期经过的格数。若每格 1 微秒,差值为 2000,周期就是 2 毫秒,频率约 500 Hz。

计数器可能在两次边沿之间回到零,必须处理回绕;长时间没有新边沿,还需要判断超时。滤波、边沿极性和计数器宽度也会影响结果。先用已知方波验证,再接真正被测信号。

到这里,定时器的几种用途就来自同一个计数过程:数到终点通知,比较时改变输出,外部边沿到来时记录位置。下一篇 系统保护 看程序不再正常前进时,怎样检测并恢复。

资料与源码