通用定时器的时基单元包含:①16位的计数器(TIMx_CNT),②16位的预分频器寄存器(TIMx_PSC),③16位的自动装载寄存器(TIMx_ARR)。
定时时间 = CK_PSC周期 * TIMx_PSC * TIMx_ARR
定时频率 = fCK_PSC / TIMx_PSC / TIMx_ARR
TIMx_PSC(预分频器寄存器):它是一个16位寄存器,可以将计数器的始终频率按1到216之间的任意值分频。(建议不要设置为0,下载程序时有时会出故障)。
TIMx_CNT(计数器寄存器):16位计数器,由CK_CNT驱动,仅当设置了计数器TIMx_CR1寄存器中的计数器使能位(CEN)为1时,CK_CNT才有效。
TIMx_ARR(自动装载寄存器):一个16位寄存器(带有缓冲器,即影子寄存器),可能取值为2到65536。
上图带阴影部分的寄存器,物理上这样的寄存器对应两个寄存器,一个是我们能够操作的,称为预装载寄存器,另一个是我们无法操作的,但在操作中实际起作用的寄存器,称为影子寄存器。
ARR( Auto Reload Register)、PSC(Prescaler)、CCRx(Capture/Compare Register x)都有影子寄存器。对应的使能或失能预装载寄存器的固件库函数如下表:
寄存器 | 固件库函数 | 例如 |
---|---|---|
ARR | void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState Newstate) | TIM_ARRPreloadConfig(TIM2, ENABLE); |
PSC | void TIM_PrescalerConfig(TIM_TypeDef* TIMx, u16 Prescaler,u16 TIM_PSCReloadMode) | TIM_PrescalerConfig(TIM2, TIMPrescaler, TIM_PSCReloadMode_Immediate); |
CCRx | void TIM_OCxPreloadConfig(TIM_TypeDef* TIMx, u16 TIM_OCPreload) | TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable); |
其中PSC寄存器第二个参数设置预分频值,可以为0~65535,建议不要取0。最后一个参数TIM_PSCReloadMode选择预分频重载模式,具体取值如下表:
TIM_PSCReloadMode | 描述 |
---|---|
TIM_PSCReloadMode_Update | TIM预分频值在更新事件装入 |
TIM_PSCReloadMode_Immediate | TIM预分频值即时装入 |
设置影子寄存器的好处是,所有真正起作用的影子寄存器(shadow register)可以在同一个时间(发生更新事件时)被更新为所对应的预装载寄存器(preload register)的内容,这样可以保证多个通道的操作能够准确地同步。
TIMx_ARR寄存器内容发生变化时,若ARPE = 0时,自动装载寄存器的内容随时可以传递到影子寄存器中,若ARPE = 1时,自动装载寄存器的内容在每一次更新事件发生时,才传递到影子寄存器。
定时器的时钟不是直接来自APB1 或APB2,而是来自于输入为APB1 或APB2 的一个倍频器,当APB1或APB2的预分频系数为1 时,这个倍频器不起作用,定时器的时钟频率等于APBx的频率。设置倍频器的目的是保证其它外设使用较低时钟频率时,TIM2~7 仍能得到较高的时钟频率。
计数器的时钟源若来自于内部时钟:则使用RCC_Configuration( )函数,来设置TIMx的内部时钟;若来自外部时钟,则不用设置。
每个TIM共有18个设置寄存器
定义的代码这里不再给出,大家可以参照<
RCC_APBxPeriphClockCmd(RCC_APBxPeriph_TIMx, ENABLE);
使能的时候一定要注意自己使用的是那个时钟,如果使用的是高速时钟,它是挂载在APB2总线上的,通用定时器和基本定时器是挂载在APB1总线上的。
TIM_DeInit(TIMx);
复位时为了使ARPE=0,让自动装载寄存器与影子寄存器直接连通。单片机上电即复位,所以一般可以省略。
// TIM_TimeBaseInitTypeDef结构体定义了TIMx的时基单元的参数
typedef struct
{
u16 TIM_Period; // 设置通用定时器TIMx的周期值(TIMx_ARR = TIM_Period + 1)
u16 TIM_Prescaler; // 设置通用定时器TIMx的预分频值(TIMx_PSC = TIM_Prescaler + 1)
u8 TIM_ClockDivision; // 不用于定时,仅仅用于计数,用于定时时不用设置
u16 TIM_CounterMode; // 设置通用定时器TIMx的计数模式
} TIM_TimeBaseInitTypeDef;
TIM_CounterMode代表定时器的计数模式,其可以设置的值如下:
定时器的计数模式由TIMx_CR1来控制
注:在计数器开启时(CEN=1),不允许从边沿对齐模式转换到中央对齐模式。
TIM_TimeBaseInit(TIMx,&TIM_TimeBaseInitStructure); //初始化通用定时器TIMx
TIM_Cmd(TIMx,ENABLE); // 使能TIMx外设
TIM_Cmd(TIMx,DISABLE); // 失能TIMx外设
外围设备TIMx,具备若干个可以引起中断的中断源或中断事件,该设备的所有的中断都只能通过指定的“中断通道”TIMx_IRQChannel向内核申请中断。
参数TIM_IT的值如下图:
注:每次进入中断后都需要清除中断标志位:TIM_ClearFlag(TIMx, TIM_Flag_Update);
它适合多种用途,包含测量输入信号的脉冲宽度(输入捕获),或者产生输出波形(输出比较、PWM、嵌入死区时间的互补PWM等),特别适合于电机控制。
高级定时器和通用定时器配置的不同之处:
高级定时器有多个中断通道:
普通定时器和高级定时器课程学习目前较少,日后学习过后一定补充。