一、STM32F407定时器简介
STM32F407系列最多包含14个定时器(TIM1~TIM14)。分为高级控制定时器、通用定时器和基本定时器。
基本定时器(TIM6、TIM7)功能最为简单,主要用于通用计时、驱动数模转换器。
通用定时器(TIM2~TIM5,TIM9~TIM14)功能最为丰富,数量众多,可用于定时,测量外部信号的脉冲宽度、频率或周期,产生单脉冲、高精度脉宽调制信号等;支持编码器接口,用于电机位置和速度检测。
高级控制定时器(TIM1、TIM8)在通用定时器功能的基础上,增加了专为电机控制、数字电源转换等高级特性。
本文及后续的定时器内容皆以通用定时器为例说明。
二、通用定时器结构(TIM2~TIM5,TIM9~TIM14)
虽然通用定时器的功能众多,但都可归为三大功能:定时、输入捕获、比较输出。这三大功能也是由定时器结构决定的,通用定时器的结构框图可分为三大部分:时基单元、输入捕获、输出比较。具体见下图。
本文先介绍时基单元,时基单元见下图。请结合图来阅读以下内容。
1、时基单元
时基单元包括计数器CNT、预分频器PSC、自动重装载寄存器ARR。
(1)计数器CNT是一个16位或32位(TIM2和TIM5)的寄存器,此寄存器可采用递增方式计数,也可采用递减方式计数,每来一个时钟信号CK_CNT,计数器的值+1或-1。
(2)计数器CNT的时钟信号CK_CNT来自于预分频器PSC的输出。预分频器PSC是一个16位的寄存器,可对预分频器时钟CK_PSC进行分频,分频系数介于1~65536。
(3)预分频器时钟CK_PSC由内部时钟CK_INT提供。内部时钟CK_INT来自于RCC的定时器时钟TIMx_CLK(84MHz)。
(4)自动重装载寄存器ARR是一个16位的寄存器,可设置为1~65536之间任何一个数。
2、计数模式
递增(向上)计数模式:计数器从0开始计数到自动装载值(自动重装载寄存器ARR里的值),然后又重新从0开始计数并且产生一个计数器溢出事件和更新中断。
递减(向下)计数模式:计数器从自动装载值(自动重装载寄存器ARR里的值)开始向下计数到0,然后从自动装载值重新开始,并产生一个计数器向下溢出事件和更新中断。
中心对齐模式(递增/递减计数):计数器从0开始计数到自动重载值-1,产生一个计数器溢出事件,然后从自动重载值开始向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数。
3、定时器时钟源TIMx_CLK
时钟源TIMx_CLK为84MHz。具体设置可见system_stm32f4xx.c文件。除了高级定时器,其他定时器都挂载在APB1总线上。
4、定时时间计算
计数器时钟信号CK_CNT的频率为:
那么1/CK_CNT即为计一个数的时间。则定时时间为:
举例:TIMx_CLK为84MHz,若分频器PSC取值8399,则CK_CNT为10KHz。那么计数器计一个数的时间为0.1ms。若定时器时间为1s,则计数器应计10000个数,注意计数器从0开始计数,那么ARR应取值9999。
三、定时器库函数
1、时基初始化库函数
void TIM_TimeBaseInit(TIM_TypeDef*TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
参数1:TIMx,x=1~14,选择定时器
参数2:结构体指针,用于初始化定时器相关参数
typedef struct
{
uint16_t TIM_Prescaler; //PSC预分频值,1~65536
uint16_t TIM_CounterMode; //计数模式,向上计数/向下计数
uint16_t TIM_Period; //自动重装载值,1~65536
uint16_t TIM_ClockDivision; //用来设置时钟分频因子
uint8_t TIM_RepetitionCounter; //该参数只用于 TIM1和TIM8
} TIM_TimeBaseInitTypeDef;
库函数使用示例:以定时器TIM2为例,定时1s
TIM_TimeBsaeInitTypeDef TIM_TimeBsaeStructure;//定义结构体
TIM_TimeBsaeStructure.TIM_Period = 10000-1;//设置自动重装载值
TIM_TimeBsaeStructure.TIM_Prescaler = 8400-1;//设置预分频值
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;//1分频即可
TIM_TimeBsaeStructure.TIM_Mode = TIM_CounterMode_Up;//向上计数,Up换成Down为向下计数
TIM_TimeBaseInit(TIM2, & TIM_TimeBsaeStructure);//完成初始化
2、使能定时器库函数
void TIM_Cmd(TIM_TypeDef * TIMx, FunctionalState NewState)
参数1:TIMx,x=1~14,选择定时器
参数2:ENABLE使能定时器;DISABLE关闭定时器
使用方法:TIM_Cmd(TIM2, ENABLE); //使能TIM2
3、使能定时器中断库函数
void TIM_ITConfig(TIM_TypeDef *TIMx, u16 TIM_IT, FunctionalState NewState)
参数1:TIMx,x=1~14,选择定时器
参数3:ENABLE使能定时器中断;DISABLE关闭定时器中断
参数2:TIM_IT中断类型,TIM_IT取值如下:
TIM_IT_Updata; //更新中断
TIM_IT_CC1; //捕获、比较中断
TIM_IT_Trigger; //触发中断
使用方法:使能TIM2更新中断
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );
4、获取中断标志位库函数
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT)
参数1:TIMx,x=1~14,选择定时器
参数2:TIM_IT中断类型,取值同上。
返回值:SET,表示对应的中断已触发;RESET,表示对应的中断未触发。
使用方法:获取TIM2的捕获比较中断
if(TIM_GetITStatus(TIM2,TIM_IT_CC1) == SET);
5、清除中断标志位库函数
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, u16 TIM_IT)
参数见上。
使用方法:清除TIM2的捕获比较中断标志位
TIM_ClearITPendingBit(TIM2,TIM_IT_CC1);

