STM32 TIM定时器中断:实现定时任务的最佳方案

一、TIM(Timer)定时器
定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断;
16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时;
不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能;
根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型。
二、定时器类型
STM32F103C8T6定时器资源:TIM1、TIM2、TIM3、TIM4,一个高级定时器,三个通用定时器。
基本定时器介绍:
自动重装载寄存器,预分频器和CNT计数器组成时基单元,完成计数计时的功能。预分频器之前,连接的是基准计数时钟的输入,由于基本定时器只能选择内部时钟,所以可以看做内部时钟(CK INT)直接连接的是预分频器,来自RCC的TINxCLK一般都是72MHZ;实际分频系数=预分频器值+1,预分频器是16位的,可以写65535,因此最大分频系数为65536。计数器是对分频后的时钟进行计数,每来一个上升沿,计数器值+1,计数器是16位的,因此最大计数值的范围是0-65535;当计数器的值等于自动重装载寄存器的值时,产生一次中断信号,并且计数器的值清零,图中向上的箭头表示更新中断,向下的箭头表示更新事件,CPU响应更新中断,定时器中断的任务就完成了。
**

– 通用定时器框图


  • 高级定时器框图
    定时中断的基本结构
    使用定时器定时中断的步骤:

    1.开启时钟。每个程序都必须的第一步,打开内部时钟源,GPIO外设。
    2.选择时基单元的时钟源。定时器定时中断选择内部时钟源。
    3.配置时基单元。配置预分频器,自动重装器和计数器这三个寄存器。
    4.配置输出中断控制,允许更新中断输出到NVIC.
    5.配置NVIC,在NVIC 中打开定时器中断的通道,并分配一个优先级。
    6.运行控制。
    7.使能定时器。开中断。
    8.写定时器中断服务程序。
    定时器中断实现没秒加1程序
    定时器初始化和中断服务程序:
  • #include "stm32f10x.h"                  // Device header
    
    void timer_Init(void)
    {
    	NVIC_InitTypeDef NVIC_InitStructure;
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    	
    	//1.开启时钟,TIM2是APB1总线的外设
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
    	//2.配置时钟单元
    	TIM_InternalClockConfig(TIM2);   //选择内部时钟驱动TIM2的时基单元
    	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;  //选择时钟分频
    	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;  //计数器模式选择
    	//定时时间的公式:CK_CNT_OV = CK_PSC / (PSC + 1) / (ARR + 1),定时1s,也就是1HZ;
    	//预分频器和计数器有一个数的偏差,因此要减1,PSC和ARR的取值0~65535;
    	TIM_TimeBaseInitStructure.TIM_Period = 10000-1;  //自动重装器的值
    	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200-1;  //预分频器的值
    	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;  //重复计数器的值,基本定时器用不到
    	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
    	
    	TIM_ClearFlag(TIM2,TIM_FLAG_Update);  //手动清除中断标志位,避免刚初始化完就进入中断
    	//3.使能中断
    	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);  //打开更新中断到NVIC的通道。
    	//4.配置NVIC
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //NVIC优先级分组
    	
    	
    	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  //选择中断通道
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  //通道使能
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  //抢占优先级
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  //响应优先级
     	NVIC_Init(&NVIC_InitStructure);
    	//5.启动定时器
    	TIM_Cmd(TIM2,ENABLE);
    }
    /*
    void TIM2_IRQHandler(void)  //中断函数
    {
    	if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET){   //中断标志位判断,确认进入中断
    		TIM_ClearITPendingBit(TIM2,TIM_IT_Update); //清除中断标志位
    	}
    }*/
    

    main:

    #include "stm32f10x.h"                  // Device header
    #include "Delay.h"
    #include "OLED.h"
    #include "Timer.h"
    uint16_t Num;
    int main(void)
    {
    	OLED_SPI_Init();
    	OLED_Init();
    	timer_Init();
    	OLED_ShowString(1,1,"Num:");
    		
    	while(1)
    	{
    		OLED_ShowNum(1,5,Num,5);
    				
    	}
    }
    void TIM2_IRQHandler(void)  //中断函数
    {
    	if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET){   //中断标志位判断,确认进入中断
    		Num++;
    		TIM_ClearITPendingBit(TIM2,TIM_IT_Update); //清除中断标志位
    	}
    }
    

    **

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32 TIM定时器中断:实现定时任务的最佳方案

    发表评论