STM32学习笔记(8)定时器相关之通用定时器
简介
STM32中有三种定时器,包括高级定时器,通用定时器,基本定时器。以STM32F103ZET6为例,有高级定时器(TIM1,TIM8),通用定时器(TIM2~TIM5),基本定时器(TIM6,TIM7)。(三种定时器功能区别)本篇主要讲解通用定时器。
STM32F1 的通用定时器是一个通过可编程预分频器(PSC)驱动的 16 位自动装载计数器(CNT)构成。
工作框图
时钟来源:
1) 内部时钟(CK_INT)
2) 外部时钟模式 1:外部输入脚(TIx)
3) 外部时钟模式 2:外部触发输入(ETR)
4) 内部触发输入(ITRx):使用 A 定时器作为 B 定时器的预分频器(A 为 B 提供时钟)。
预分频器:将计数器的时钟频率按1到65536之间的任意值分频。它是基于一个(在TIMx_PSC寄存器中的)16位寄存器控制的16位计数器。这个控制寄存器带有缓冲器,它能够在工作时被改变。预分频器参数在下一次更新事件到来时被采用。
计数器模式:
1.向上计数模式 :计数器从0计数到自动加载值(TIMx_ARR计数器的内容),然后重新从0开始计数并且产生一个计数器溢出事件;
2. 向下计数模式 :计数器从自动装入的值(TIMx_ARR计数器的值)开始向下计数到0,然后从自动装入的值重新开始并且产生一个计数器向下溢出事件;
3.*对齐模式(向上/向下计数) :计数器从0开始计数到自动加载的值(TIMx_ARR寄存器)-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器下溢事件;然后再从0开始重新计数。
每次计数器溢出时可以产生更新事件,在TIMx_EGR寄存器中(通过软件方式或者使用从模式控制器)设置UG位也同样可以产生一个更新事件。
定时时间计算
以RCC的TIMxCLK作为时钟来源为例子,其频率为72MHz,则TimeOut=(ARR+1)(PSC+1)/Tclk。即溢出时间=(自动装载值+1)(预分频系数+1)/频率。此时一般使得预分频系数为71或7199等,便于计算。
初始化相关参数
typedef struct
{
uint16_t TIM_Prescaler;//预分频系数
uint16_t TIM_CounterMode;//计数模式
uint16_t TIM_Period; //自动装入值
uint16_t TIM_ClockDivision;//设置时钟分频因子
uint8_t TIM_RepetitionCounter; //重复计数器
} TIM_TimeBaseInitTypeDef;
使用步骤
1.使能定时器时钟;RCC_APB1PeriphClockCmd();
2.初始化定时器,配置ARR,PSC;TIM_TimeBaseInit();
3.开启定时器中断,配置NVIC;TIM_ITConfig(); NVIC_Init();
4.使能定时器;TIM_Cmd();
5.编写相应中断服务函数。TIM3_IRQHandler();
设置一个500ms的定时器中断为例:
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitSrtue;//初始化相应结构体
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能定时器时钟
TIM_TimeBaseInitSrtue.TIM_Prescaler=psc;//预分频系数
TIM_TimeBaseInitSrtue.TIM_CounterMode=TIM_CounterMode_Up;//向上计数
TIM_TimeBaseInitSrtue.TIM_Period=arr;//自动装载值
TIM_TimeBaseInitSrtue.TIM_ClockDivision=TIM_CKD_DIV1;//设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitSrtue);//初始化TIMx的时间基数单位
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//使能定时器的更新中断
//中断优先级NVIC设置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM3,ENABLE);//使能定时器
}
void TIM3_IRQHandler(void)//中断服务函数
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
{
LED1=!LED1;
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);//清除相应标志位
}
之后,在主函数里使用该函数并使用相应参数即可
TIM3_Int_Init(4999,7199);//500ms