stm32定时器笔记

发布时间 2023-04-02 21:58:58作者: wegret

  参考资料: STM32-定时器详解

        STM32F103C8T6的学习(5)——定时器

        TM32定时器之预分频器详解

        stm32之TIM-基本定时器应用实例(详细)

        STM32 TIM 定时时间的计算

        《STM32单片机应用基础与项目实践》

 

  单片机具有一些外设,即外围功能模块。这些外设可以通过IO,SPI,I2C等总线控制。

  常见的外设:基本IO,定时器TIM,RTC闹钟,ADC模数等等……

定时器概括

  定时器是stm32中的一个常见外设,可以对输入的时钟进行计数,计数达到设定值触发中断。

  stm32有8个定时器,根据复杂度和应用场景分为:2个高级定时器(TIM1,TIM8),4个通用定时器(TIM2到TIM5),2个基本定时器(TIM6,TIM7)。

  其中基本定时器只有大容量的STM32F103RC才有。而STM32F103C8T6只有TIM1,TIM2,TIM3,TIM4(一个高级定时器,三个通用定时器)。

时钟来源

  计时器时钟可以由以下时钟源提供:

  (1) 内部时钟(CK_INT)。使用这个需要预分频器,见下。

  (2) 外部时钟模式1:外部输入脚(Tix)

  (3) 外部时钟模式2:外部触发输入(ETR)

  (4) 内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器。

预分频器

  stm32中,定时器的时钟源为频率极高的内部时钟时。不分频极其容易溢出。例如$72MHz$的时钟,$72MHz=72*10^6Hz$,一秒计数$7.2*10^7$次。16位最高到$65535$,溢出只需要$\frac{65535}{7.2*10^7}=0.0009s$!因此要对时钟进行分频输出。除此之外,预分频的好处还有:可以得到更准确的时间。

 

定时器初始化

  预分频系数psc:对系统时钟进行分频。

  重装载值arr:计数达到这个值后重新装载。

  stm32的所有外设初始化都是通过库中的结构体和初始化函数,定时器TIM也是这样。这个结构体类型是 TIM_TimeBaseInitTypeDef ,在库中的定义如下:

 

/* TIME 这个结构体可以用于所有的TIMx,除了TIM6和TIM7 */
typedef struct
{
  uint16_t TIM_Prescaler;             // 预先分频系数psc,可以是0~65535间的数 
  uint16_t TIM_CounterMode;           //   (计数器模式,基本定时器只能向上计数,不用设置) 
  uint16_t TIM_Period;                // 重装载值arr,可以理解为周期 
  uint16_t TIM_ClockDivision;         //   (时钟分频,不用设置) 
  uint8_t TIM_RepetitionCounter;      //   (重复计数器,不用设置,只对TIM1和TIM8两个高级定时器起作用的参数) 
} TIM_TimeBaseInitTypeDef;   

 

定时器间隔:

  在系统时钟是$72MHz$时,进入中断程序的时间间隔是$((1+psc)/72M)*(1+arr)$,在arr为$10000-1$,psc为$7200-1$时,中断时间为$1s$。

 

定时器初始化代码:

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;    // TIM结构体声明 
    NVIC_InitTypeDef NVIC_InitStructure;            // 嵌套向量中断结构体声明 
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);     //打开TIM6的时钟 
    
    /* 配置时基 */
    TIM_TimeBaseStructure.TIM_Period = arr;                     // 设置arr 
    TIM_TimeBaseStructure.TIM_Prescaler =psc;                     // 设置psc 
    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;         // 不分频 
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数 
    TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);             // TIM6初始化 
     
    NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;              // TIM6中断 
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             // 打开IRQ通道 
    NVIC_Init(&NVIC_InitStructure);                              // 初始化NVIC 
    
    TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);    // 开启定时器 
    TIM_Cmd(TIM6, ENABLE);                      // 打开TIM6外设 

   其中,TIM6定时器的中断程序是库中的 TIM6_IRQHandler ,初始时是空函数,使用时需要直接在其上修改,或者将其注释后再重新写。