没志青年
发布于 2025-06-13 / 49 阅读
0

32单片机 - 定时器

定时器

定时器分类:

全是自动重装载计数器。

定时器

说明

基本定时器

16 位自动重载递增计数器

定时中断(只能向上计数)。或作为 DAC 的时基。

通用定时器

16 位或 32 位递增、递减和递增/递减自动重载计数器。

定时中断、输入捕获、输出比较

高级定时器

16 位递增、递减、递增/递减自动重载计数器。

定时中断、输入捕获、输出比较、互补输出、死区插入、刹车等功能。

在数据手册中查看:

定时器时钟来源及应用场景:

时钟符号

时钟来源

应用场景

CK_INT

内部时钟(来自 APB1/APB2 总线)

定时中断、PWM输出

TIMx_ETR

外部时钟引脚输入(GPIO)

定时中断、输入捕获

ITRx

其它定时器输入

一个定时器作为另一个定时器的预分频器

定时器主从模式:

  • 主模式:定时器主动输出:比较输出、产生更新中断等

  • 从模式:定时器被动接收输入,输入捕获,其它定时器输入等

计数模式

  • 向上计数:

  • 向下计数:

  • 中心对齐:

事件和中断

在高级定时器中,有重复计数器,于一个分频器,原来溢出一次就触发一次,配置为 N 后,N 次溢出才触发一次。

一、定时中断

定时器本质是计数器。

首先,输入的时钟 CK_INT 决定了计数的快慢,

可以看到,图中的寄存器后面有个黑影,叫做影子寄存器,影子寄存器是实际上起作用的寄存器,但是无法直接操作。

当修改了自动重载寄存器的值时,

  • 设置了直接生效:

  • 没设置直接生效:当计数周期结束时,避免在参数更新过程中产生干扰。

当自动重装载寄存器的值等于计数寄存器的值的时候,便会产生中断和其它事件。

定时参数计算

公式推导过程:

(1)计算定时时间

a. 根据频率得到周期:

t = \frac{1}{F_t /p}

p 为分频值

b. 定时时间 = n 个周期:

T_{out}= t*n

(2)代入 p 和 n

  • p = PSC + 1:PSC 是分频系数,为预分频寄存器的值,实际分频比是 PSC + 1。因为硬件是从 0 开始的,计数到 PSC 才会输出一个时钟,也就是 PSC+1 个时钟才会给定时器输入一个时钟,实现 p 倍分频。

  • n = ARR + 1:ARR 为重装载寄存器的值。定时器在 CNT== ARR 时会产生中断事件,从 0 到 n 共计 n+1 个数,它在 n+1 的时候会产生中断,也就是会多计一个数,因此如果想计 n 个数就中断,需要将寄存器的值设置为 n-1。感觉不对

T_{out} = t * n = \frac{1}{F_t/p} * n=\frac{1}{F_t/(PSC+1)} * (ARR + 1) = \frac{(ARR+1)*(PSC+1)}{F_t}

-1 的关键原因:硬件计数从 0 到 ARR,共 ARR+1 次

定时器不是在“数次数”,而是在“遍历状态”,而状态编号从 0 到 ARR

百分比和比较值转换

已知占空比:

duty(\%)=\frac{比较值}{周期}*100

周期 = Period +1 ,是整数,不是 999 这样的,是1000

所以:

比较值=duty*周期*100

八种主模式:

F0标准库:

void Timer3_Initializes(void)
{
    TIM_TimeBaseInitTypeDef  timer_struct = {0};

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

	timer_struct.TIM_RepetitionCounter = 0;   // 重复计数值
	timer_struct.TIM_Period = 1000; 
	timer_struct.TIM_Prescaler =48; 
	timer_struct.TIM_ClockDivision = TIM_CKD_DIV1; 
	timer_struct.TIM_CounterMode = TIM_CounterMode_Up;

	TIM_TimeBaseInit(TIM3, &timer_struct);
	TIM_ITConfig(TIM3,TIM_IT_Update, ENABLE);     // 开中断
	TIM_Cmd(TIM3,ENABLE);                         // 开启定时器
}


void TIM3_IRQHandler(void)  
{
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) 
    {
        // 处理逻辑......
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update); 
    }
}

二、从模式

从模式:

  • 外部时钟模式

  • 复位模式

  • 门模式

  • 触发模式

触发源:

  • 定时器4个输入通道

外部时钟模式

共 7 个源

复位模式

此时定时器的时钟可以选择为:

  • 内部时钟

  • ETR 外部时钟

触发源还是 7 个:

  • ITR0~4、TI1F_ED、TI1FP1、ETR(时钟源为内部时钟时可选择)

触发源触发一下,定时器复位:

  • CNT 计数器清零

  • 产生定时器更新事件

  • 影子寄存器更新到主寄存器

判断更新中断产生的原因:

门模式

就是控制定时器是否工作

比如上升沿开启定时器,下降沿暂停定时器。

触发模式

仅用于启动定时器计数。

配合“单脉冲模式”使用,这个模式就是计数到自动重装载后就停止运行了。

三、输入捕获

输入捕获可用于测量外部信号频率、脉宽、占空比,高级定时器有4个输入通道,4个输出通道。

输入捕获只有一个中断事件(捕获N次时触发)。

信号处理流程:

  1. 信号进来后,首先进入滤波器去除干扰

  2. 接着边沿检测器检测是上升沿还是下降沿

  3. 根据上面的流程图,信号会进入特定的预分频器处理,会产生中断

  4. 最后“捕获/比较寄存器”会计数,当这个值达到了“自动重装载寄存器”的值,便会产生中断

信号选择:

  • 直接信号 :信号来自自己的通道为直接。

  • 间接信号:信号来自其它通道为间接。通道1和2为一对,通道3和4为一对,可组合使用。

  • TRC信号:

    • 其他定时器信号输入

    • TI1F_ED:捕获通道1的上升沿和下降沿信号,直接可产生中断事件,不用经过分频器再产生

信号的选择丰富多样,根据实际使用场景选择。

电机中的三相霍尔传感器可以用到,信号输出给通道1。

TRGI 是定时器的触发输入信号,它连接到了定时器内部的 从模式控制器(Slave Mode Controller),可以用来:

  • 作为计数器的时钟源

  • 触发定时器启动、复位

同时产生 TGI 中断信号,这个是写代码的中断处理函数。

TRGO 信号:由触发控制器产生的硬件触发信号,

  • 可触发DAC/ADC外设

  • 可触发其它定时器,就是其它定时器的ITR输入信号

八种从模式:

(1)输入捕获用于测量频率

(1)输入捕获用于测量占空比

(1)输入捕获用于测量脉宽

脉宽是一个周期内高电平的持续时间。

测量脉宽:一个通道捕获上升沿,一个捕获下降沿

脉宽 = (大值 - 小值)*

计数

PWM 测量

定时器同时启动

定时器级联

一个定时器的 TRGO 接另一个定时器的 TRGI,这样串联起来。

例如:

举个例子,实际上不会这么用。

编码器接口

定时器支持增量型旋转编码器功能,免去了手写中断捕获逻辑,节省 CPU 资源。

编码器有两个接口,称为通道 A 和通道 B,分别输出占空比为 50% 的 PWM 方波,旋转时通道 A 和 B 相位差为90°

  • 空闲:统一输出低电平或高电平

  • 顺时针(CW)旋转:A 相领先 B 相 90°,或者相反。

  • 逆时针(CCW)旋转:B 相领先 A 相 90°,或者相反。

不同的编码器,它的输出行为不一样,例如:

该编码器的行为:

  • 空闲时:输出低电平

  • 24° (15Detent):每 24° 有一个点位,共 15 个点位,也就是旋转一圈输出 15 个上升沿(如果默认是高电平那就是下降沿)。

  • Detent 表示有机械卡位,不能连续旋转。

  • 顺时针旋转:A 相领先 B 相90°

  • 逆时针旋转:B 相领先 A 相90°

判断旋转方向:

  • 顺时针:A 上升沿时 B 为低电平

  • 逆时针:A 上升沿时 B 为高电平

定时器自带编码器功能,正转时数值+1,反转时数值-1,数值保存在定时器的计数寄存器中,定时器中的编码器对上下边沿都处理。


如何理解这个图?

  • 【TI1FP1 信号】在【上升】沿的时候,如果【TI2FP2 信号】为【高】电平,则【向下计数】

  • 【TI1FP1 信号】在【上升】沿的时候,如果【TI2FP2 信号】为【低】电平,则【向上计数】

【仅在TI1计数】时,此时检测的是 TI1FP1 的信号,如果在上升沿的时候 T21FP2 的电平为高电平,则向下计数;反之则向上计数。

对于这个编码器,将A通道接TI1,B接TI2,则数值增加表示顺时针旋转,数值减小表示逆时针旋转。

编码器的数值保存在 CNT 计数器中,所以每个定时器只能处理一个编码器。

怎么在代码里知道是正转还是反转呢?

输入异或功能

霍尔传感器

三、PWM 输出

用到定时器的输出比较功能。

和定时中断一样,先计算设置PWM的频率。

然后设置【捕获/比较寄存器】的值,。

每计一个数,比较计数器和捕获/比较寄存器的值,

计数的

PWM 模式

模式

CNT < CCR

CNT ≥ CCR

PWM1(常用)

有效电平

无效电平

PWM2

无效电平

有效电平

互补输出

死区插入

刹车功能

其它应用

定时器作为时基

定时器触发ADC

定时器用于消抖

例如,在分布式 IO 的数字量输入模块中,有16个通道,每个通道都需要做消抖处理,如果用一般的做法 delay_ms 阻塞等待,那16个通道的延时是不可接受的,造成系统响应不及时,会错过一些信号的输入。

比如在给第2个通道消抖,但此时第8个通道输入了,等第2个通道消抖结束,第8个通道的信号也结束了,那就错过了第8个通道,这个系统就是不可用的了。

定时器设置为 1 ms,然后在