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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章