一.定时器介绍
STM32F1的定时器非常多,由2个基本定时器(TIM6、TIM7)、4个通用定时器(TIM2-TIM5)和2个高级定时器(TIM1、TIM8)组成。基本定时器的功能最为简单,类似于51单片机内定时器。通用定时器是在基本定时器的基础上扩展而来,增加了输入捕获与输出比较等功能。高级定时器又是在通用定时器基础上扩展而来,增加了可编程死区互补输出、重复计数器、带刹车(断路)功能,这些功能主要针对工业电机控制方面。
1.1 通用定时器简介
STM32F1的通用定时器包含一个 16 位自动重载计数器(CNT),该计数器由可编程预分频器(PSC)驱动。STM32F1的通用定时器可用于多种用途,包括测量输入信号的脉冲宽度(输入捕获)或者生成输出波形(输出比较和PWM)等。 使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。STM32F1 的每个用定时器都是完全独立的,没有互相共享的任何资源。
STM32F1的通用定时器TIMx (TIM2-TIM5 )具有如下功能:
(1)16 位向上、向下、向上/向下自动装载计数器(TIMx_CNT)。
(2)16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为 1~65535之间的任意数值。
(3)4个独立通道(TIMx_CH1-4),这些通道可以用来作为:
A.输入捕获
B.输出比较
C. PWM 生成(边缘或中间对齐模式)
D.单脉冲模式输出
(4)可使用外部信号(TIMx_ETR)控制定时器,且可实现多个定时器互连(可以用1个定时器控制另外一个定时器)的同步电路。
(5)发生如下事件时产生中断/DMA请求:
A.更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
B.触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
C.输入捕获
D.输出比较
(6)支持针对定位的增量(正交)编码器和霍尔传感器电路
(7)触发输入作为外部时钟或者按周期的电流管理
二、通用定时器配置步骤
(1)使能定时器时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE); //使能TIM4时钟
(2)初始化定时器参数,包含自动重装值,分频系数,计数方式等
void TIM_TimeBaseInit(TIM_TypeDef* TIMx , TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct); //第一个参数为使用的定时器,第二个参数为配置结构体的地址
结构体TIM_TimeBaseInitTypeDef的成员
typedef struct{
uint32_t TIM_Period; //定时器周期
uint16_t TIM_Prescaler; //定时器预分频器
uint16_t TIM_CounterMode; //计数模式
uint16_t TIM_ClockDivision; //时钟分频
}TIM_TimeBaseInitTypeDef;
TIM_Period | 设置了在下一个更新事件装入活动的自动重装载寄存器周期的值 |
---|---|
TIM_Prescaler | 设置了用来作为TIMx时钟频率除数的预分频值 |
TIM_CounterMode | 计数器模式 |
---|---|
TIM_CounterMode_Up | TIM向上计数 |
TIM_CounterMode_Down | TIM向下计数 |
TIM_CounterMode_CenterAligned1 | TIM中央对齐模式1计数模式 |
TIM_CounterMode_CenterAligned2 | TIM中央对齐模式2计数模式 |
TIM_CounterMode_CenterAligned3 | TIM中央对齐模式3计数模式 |
TIM_ClockDivision | 时钟分割 |
---|---|
TIM_CKD_DIV1 | tDTS = Tck_tim |
TIM_CKD_DIV2 | tDTS = 2Tck_tim |
TIM_CKD_DIV3 | tDTS = 3Tck_tim |
定时器定时时间计算公式如下:
Tout= ((per)*(psc+1))/Tclk; //per为周期,psc为预分频,Tclk为时钟分割后的时钟频率
(3)设置定时器中断类型,并使能
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState); //使能或失能指定的TIM中断
NewState为ENABLE(使能)或DISABLE(失能)
TIM_IT | 描述 |
---|---|
TIM_IT_Update | TIM中断源 |
TIM_IT_CC1 | TIM捕获/比较1中断源 |
TIM_IT_CC2 | TIM捕获/比较2中断源 |
TIM_IT_CC3 | TIM捕获/比较3中断源 |
TIM_IT_CC4 | TIM捕获/比较4中断源 |
TIM_IT_Trigger | TIM触发中断源 |
(初学一般使用TIM_IT_Update较多)
(4)设置定时器中断优先级,使能定时器中断通道
NVIC初始化库函数是NVIC_Init();
(5)开启定时器
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState); //NewState为ENABLE(使能)或DISABLE(失能)
(6)编写定时器中断服务函数
void TIM4_IRQHandler(void){
if(TIM_GetITStatus(TIM4,TIM_IT_Update)){
//添加处理事件
}
TIM_ClearITPendingBit(TIM4,TIM_IT_Update); //清除中断标志
}
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT); | 检查中断发生与否 |
---|---|
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT); | 清除中断标志 |
三、总结写法如下
/*定时器配置函数
参数:pre为定时器周期,psc为预分频数
返回值:void
功能:配置并开启定时器
*/
void TIM4_Init(u16 pre,u16 psc){
TIM_TimeBaseInitTypeDef TIM_InitStructure; //定时器配置结构体
NVIC_InitTypeDef NVIC_InitStructure; //中断优先级配置结构体
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE); //使能TIM4的时钟
TIM_InitStructure.TIM_Period = pre;
TIM_InitStructure.TIM_Prescaler = psc;
TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4,&TIM_InitStructure); //定时器初始化
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE); //使能定时器
TIM_ClearITPendingBit(TIM4,TIM_IT_Update); //清除触发标志,避免开启误触发
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; //配置中断源
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //主优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断
NVIC_Init(&NVIC_InitStructure); //中断初始化
TIM_Cmd(TIM4,ENABLE); //开启定时器
}
/*中断函数
返回值:void
功能:执行中断事件
*/
void TIM4_IRQHandler(void){
if(TIM_GetITStatus(TIM4,TIM_IT_Update)){
//添加事件
}
TIM_ClearITPendingBit(TIM4,TIM_IT_Update);
}