Skip to content

定时器

TIM (Timer) 定时器是嵌入式开发中最强大、最灵活的外设,没有之一。

为什么需要 TIM?(解决痛点)

在没有定时器之前,如果你想实现“每隔 1 秒闪烁一次 LED”,你只能写“死循环延时”:

c
// 软件延时 (Software Delay)
// 缺点:CPU 傻傻地数数,什么别的事都干不了(阻塞 Blocked)
void delay() {
   for(int i=0; i<1000000; i++) { __NOP(); } 
}

while(1) {
    LED_ON();
    delay(); // CPU 卡死在这里
    LED_OFF();
    delay(); // CPU 卡死在这里
}

TIM 的出现解决了这个问题: 它是一个独立的硬件模块,哪怕 CPU 正在睡觉或者正在算复杂的算法,TIM 依然在角落里默默地、精准地数数。数到了时间,它就戳一下 CPU(触发中断)。

TIM 的核心原理:三个关键寄存器

CNT (Counter)

当前计数值:定时器的核心是一个计数器(Counter),它会不断地数数。

PSC (Prescaler)

预分频器: 它可以将定时器的输入时钟(通常是系统时钟)分频,从而实现对定时器计数速度的调整。例如,将系统时钟分频为 1000,就可以实现 1ms 为一个计数单位。

  • 0, 1, 2, 3 ... 一直往上加。

  • PSC = 7199:相当于 7200 分频。此时 TIM 的计数频率变成 72MHz / 7200 = 10kHz(一秒数 10,000 下)。

ARR (Auto-Reload Register)

自动重装载值: 当计数器(CNT)数到 ARR 时,就会触发一个事件(如中断),并将 CNT 重置为 0。

  • 当 CNT == ARR 时,定时器这就叫“溢出 (Update)”,触发中断,然后 CNT 瞬间清零,从头开始数。

时间计算公式

假设系统主频是 72MHz,我们要实现 1秒 的定时中断。

公式: 频率=72,000,000/(PSC+1)/(ARR+1)

  • PSC (分频): 设为 7199
    • 定时器现在的 频率 = 72,000,000 / 7200 = 10,000Hz (每秒数 1万 下)。
    • 也就是每 0.1ms 数一下。
  • ARR (重装值): 设为 9999
    • 它从 0 数到 9999,一共数了 10,000 下。
    • 耗时 = (ARR+1) x 0.1ms = 1000ms = 1s
c
TIM_TimeBaseStructure.TIM_Prescaler = 7200 - 1; // PSC: 0~7199
TIM_TimeBaseStructure.TIM_Period = 10000 - 1;   // ARR: 0~9999
// 结果:每 1 秒触发一次中断

(为什么要 -1?因为计算机是从 0 开始数的,0~7199 刚好是 7200 个数)

总结

  • TIM 是嵌入式开发的节拍器。

    • CNT 是跑腿的(数数)。

    • PSC 是控制步频的(调节快慢)。

    • ARR 是终点线(设定目标)。

学会了 TIM,你就可以抛弃傻傻的 delay() 函数