TIM基本定时器
1.定时器的分类
以STM32F1系列为例,它的定时器可以根据其特性和功能被分为三大类:
基本定时器:
- 包括:TIM6和TIM7。
- 特点:基本定时器是16位,只能向上计数的定时器,通常用于简单的定时操作。它们没有外部触发输入和输出比较功能,因此不能直接生成PWM信号或用于输入捕获等复杂应用。基本定时器的时钟只能来源于内部时钟。
通用定时器:
- 包括:TIM2至TIM5。
- 特点:通用定时器也是16位,但相比基本定时器,它们更加灵活,具有更多的功能,如可以向下计数、有多个外部触发输入和输出比较通道,能够用于生成PWM信号、输入捕获、输出比较等。这些定时器的时钟源既可以是内部时钟,也可以是外部时钟。
高级定时器:
- 包括:TIM1和TIM8。
- 特点:高级定时器是最复杂且功能最丰富的定时器类型,在STM32F1系列中,它们能够提供更多的功能,如更多的输出比较通道(可达7路PWM输出),支持更复杂的定时器链路、死区生成、刹车输入等高级控制功能,非常适合电机控制、电源管理等需要精确控制的场合。这些定时器同样具有向上/向下计数能力,并且可以使用内部或外部时钟源。
如下图:
2.定时器运行流程
基本定时器的框图如下:
主要特性:
16位递增计数器(计数值:0~65535)
16位预分频器(分频系数:1~65536)
定时器主要分为时钟源,控制单元和计数部分,基本定时器的时钟源只能来自芯片内部时钟。其中在计数部分,预分频器和自动重装载寄存器具有影子寄存器,定时器的运行流程为:
初始化配置:
- 时钟使能:首先,需要通过系统时钟控制器(RCC)使能给定基本定时器的时钟。
- 配置预分频器(PSC):设置预分频寄存器的值,以降低定时器时钟频率到所需范围。例如,若APB1总线时钟为72MHz,可以通过设置PSC来分频得到较低的计数频率。
- 设置自动重载值(ARR):在自动重载寄存器中设置一个值,当计数器达到这个值时将产生更新事件并重置计数器。这决定了定时器的周期。
启动定时器:
- 控制寄存器设置:通过设置定时器控制寄存器(如TIMx_CR1),启用定时器的计数器(使能计数EN位)。
计数过程:
- 一旦定时器被启动,其计数器(CNT)从0开始递增,每次递增都是基于预分频后的时钟频率。
- 当CNT的值与ARR中的预设值相匹配时,会发生一个更新事件(Update Event)。
- 更新事件会自动将CNT寄存器复位为0,并且如果配置了中断或DMA请求,这些请求也会在此时被触发。
影子寄存器的作用:
- 我们通常配置的是“可见”的寄存器(预加载寄存器)ARR和PSC,这些配置在适当的时机(更新事件)才会反映到实际控制定时器运行的“不可见”寄存器,即影子寄存器中。影子寄存器确保了在计数过程中参数的平滑过渡,避免了在计数周期内因参数突变而引起的不连续或错误行为。
中断处理(可选):
- 如果在控制寄存器中设置了中断允许位,那么在更新事件发生时,CPU会接收到中断请求,并执行对应的中断服务程序(ISR)。在ISR中,用户可以执行特定的任务,如数据处理、状态改变等。
关闭定时器(可选):
- 如果不再需要定时器,可以通过清除控制寄存器中的使能位来停止定时器的计数。
3.基本定时器的配置流程
TIM_TimeBaseInitTypeDef TIM_BaseInitStu;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6 | RCC_APB1Periph_TIM7, ENABLE);
TIM_BaseInitStu.TIM_Prescaler =7200 - 1; //预分频值 TIM_Period x TIM_Prescaler / 时钟频率
TIM_BaseInitStu.TIM_Period = 10000 - 1; //自动装载值
TIM_TimeBaseInit(TIM6,&TIM_BaseInitStu);
TIM_TimeBaseInit(TIM7,&TIM_BaseInitStu);
TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
TIM_ITConfig(TIM7, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM6, DISABLE);
TIM_Cmd(TIM7, DISABLE);
TIM_TimeBaseInitTypeDef TIM_BaseInitStu;
定义了一个定时器基础初始化结构体变量,用于存储定时器初始化的相关配置。RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6 | RCC_APB1Periph_TIM7, ENABLE);
通过RCC(Reset and Clock Control)外设时钟控制函数,使能了APB1总线下TIM6和TIM7定时器的时钟。这是配置任何外设之前必须的步骤。
3-4.
TIM_BaseInitStu.TIM_Prescaler = 7200 - 1;
设置TIM6和TIM7的预分频器值为7199(因为预分频值是从0开始计数,所以7200-1=7199)。这表示定时器时钟将被分频7199次,具体分频效果取决于TIM6和TIM7所连接的时钟频率。TIM_BaseInitStu.TIM_Period = 10000 - 1;
配置自动重载寄存器(ARR)的值为9999,意味着当计数器从0计数到9999时,将产生一个更新事件并重置计数器。
5-6.
TIM_TimeBaseInit(TIM6, &TIM_BaseInitStu);
使用之前配置的结构体TIM_BaseInitStu
来初始化TIM6定时器的基础计时功能。TIM_TimeBaseInit(TIM7, &TIM_BaseInitStu);
同样地,初始化TIM7定时器。
7-8.
TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
允许TIM6在更新事件发生时产生中断(即计数器达到ARR值时)。TIM_ITConfig(TIM7, TIM_IT_Update, ENABLE);
同样为TIM7配置更新中断。
9-10.
TIM_Cmd(TIM6, DISABLE);
禁止TIM6定时器开始计时。TIM_Cmd(TIM7, DISABLE);
同样禁止TIM7定时器开始计时。
我们把定时器设置自动重装载寄存器 ARR 的值为 10000,设置时钟预分频器为 7199, 则驱动计数器的时钟:CK_CNT = CK_INT / (7199+1)=0.01M, 则计数器计数一次的时间等于:1/CK_CNT=100us,当计数器计数到 ARR 的值 10000时, 产生一次中断,则中断一次的时间为:1/CK_CNT*ARR=1s。
4.中断配置
NVIC_InitTypeDef NVIC_InitStu;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStu.NVIC_IRQChannel = TIM6_IRQn | TIM7_IRQn;
NVIC_InitStu.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStu.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStu.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStu);
NVIC_InitTypeDef NVIC_InitStu;
定义了一个NVIC初始化结构体类型的变量NVIC_InitStu
,用于存放中断相关的配置信息。NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
调用此函数来配置中断优先级分组。这里选择了优先级分组1,STM32的中断优先级分为5个级别(0-4,0为最高),分组1意味着有1位用于抢占优先级,3位用于子优先级。这意味着最多可以配置8种不同的抢占优先级和8种子优先级组合。
3-7. 配置NVIC_InitStu
结构体的成员:
NVIC_InitStu.NVIC_IRQChannel = TIM6_IRQn | TIM7_IRQn;
设置需要配置的中断通道,这里同时配置了TIM6、TIM7的中断。NVIC_InitStu.NVIC_IRQChannelCmd = ENABLE;
启用上述指定的中断通道。NVIC_InitStu.NVIC_IRQChannelPreemptionPriority = 1;
设置抢占优先级为1(在分组1的情况下,范围是0-7,1表示较高中断优先级)。NVIC_InitStu.NVIC_IRQChannelSubPriority = 1;
设置子优先级也为1(在本分组中,范围同样是0-7,数值越小优先级越高)。
NVIC_Init(&NVIC_InitStu);
最后,使用NVIC_Init
函数,根据NVIC_InitStu
结构体中设定的参数来初始化指定的中断通道,完成中断优先级的配置。