zoukankan      html  css  js  c++  java
  • TIM——基本定时器

     

    stm32f1系列,有基本定时器、通用定时器、高级定时器三类TIM定时器。其中,TIM6/7是本文要讲的基本定时器。

    基本定时器TIM6/7是16位的只能向上计数的定时器,只能用于定时。而通用定时器和高级定时器有更多的功能,如还可以进行输出比较、输入捕捉等功能,相关的介绍会写在后面的文章,这里只讲基本定时器。

    先看看基本定时器的框图,如图24-1。

    图24-1

    时钟源

    我们查阅参考手册RCC章节的时钟树可以知道,RCC的定时器时钟TIMxCLK,即内部时钟CK_INT是由APB1预分频器分频后提供。如图24-2所示,如果APB1预分频系数为1,,则频率不变,否则频率为2倍。即此时用于分频的APB1的预分频系数为2,所以TIMxCLK = 36 * 2 = 72MHz。

    图24-2

    计数器时钟

    如图24-1的框图,计数器时钟由内部时钟CK_INT提供,经过PSC预分频器后得到CK_CNT。PSC是一个16位的预分频器,可以对定时器时钟TIMxCLK进行1~65536之间的任何一个数进行分频。分频后的CK_CNT值的计算在参考手册TIMx_PSC寄存器描述里有提到,如图24-3。

    图24-3

    即CK_CNT = CK_PSC/(PSC[15:0]+1)。

    计数器

    计数器CNT是一个16位的计数器,只能往上计数,最大计数值为65535。

    自动重装载寄存器TIMx_ARR

    TIMx_ARR寄存器里存着最大的计数值,当计数到该值时,会产生中断。当然了你得使能了中断才可以。

    定时时间计算

    计一个数的时间是1/CK_CNT,产生一次中断的时间为(ARR+1)/CK_CNT。如果在中断服务程序里设置一个变量time用于记录中断次数,则定时时间为:(ARR+1)/CK_CNT*time。

    TIM_TimeBaseInitTypeDef

    如图24-4为基本定时器TIM_TimeBaseInitTypeDef结构体定义。

    图24-4

    • TIM_Prescaler:指定定时器预分频器数值,由TIMx_PSC寄存器配置,可设置范围为0x0000~0xFFFF,即0~65535;
    • TIM_CounterMode:计数模式,可分为向上计数、向下计数以及三种中心对齐模式。而基本定时器只能向上计数;
    • TIM_Period:计数器周期,即自动重装载寄存器TIMx_ARR的值,在事件生成时更新到影子寄存器,由TIMx_CR1寄存器的ARPE位配置是否使能缓冲;
    • TIM_ClockDivision:时钟分频,配置定时器时钟CK_INT频率与数字滤波器采样时钟频率分频比,基本定时器没有这个功能,不用设置;
    • TIM_RepetitionCounter:重复计数器,属于高级控制寄存器专用寄存器位,利用它可以很容易控制输出PWM个数,这里不用设置。

    定时1s实验

    例如,需要做一个1s的定时,CK_PSC=72MHz,则PSC=71,那么CK_CNT=1MHz,

    • 计一个数时间:1/CK_CNT = 1/1MHz = 1us,
    • 中断一次的时间:(ARR+1)/CK_CNT = (999+1)/1MHz = 1ms,
    • 则定时时间:(ARR+1)/CK_CNT*time = 1ms*1000 = 1s

    我们用led的亮灭状态变化来展示1s的定时。

    初始化TIM_TimeBaseInitTypeDef

    前文提到的TIM_TimeBaseInitTypeDef结构体有5个成员,但基本定时器TIM6/7只用到了TIM_Prescaler和TIM_Period这两个成员,其他三个是通用定时器和高级定时器才会用到的。

    /**
      * @brief  基本定时器配置
      * @param  无
      * @retval 无
      */
    static void BASIC_TIM_Mode_Config(void)
    {
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);   // 内部时钟72MHz
    
        TIM_TimeBaseStructure.TIM_Period = 999;                // 自动重装载寄存器的值	
        TIM_TimeBaseStructure.TIM_Prescaler= 71;               // 预分频器数值
        TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
    
        TIM_ClearFlag(TIM6, TIM_FLAG_Update);                  // 清除计数器中断标志位
        TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
    
        TIM_Cmd(TIM6, ENABLE);	
    }
    

    中断优先级配置

    有关中断配置相关已经在之前的文章介绍过,有不清楚的地方可移步阅读。这里只说几个配置的关键点。可配置中断优先级分组为0,即0位抢占优先级,4位子优先级。配置中断源为TIM6_IRQn。

    /**
      * @brief  中断优先级配置
      * @param  无
      * @retval 无
      */
    static void BASIC_TIM_NVIC_Config(void)
    {
        NVIC_InitTypeDef NVIC_InitStructure; 
    
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);		
        NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;	
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;	 
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;	
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
    }
    

    中断函数

    中断函数在stm32f10x_it.c文件里配置。

    extern volatile uint32_t time;            // 该变量定义在main()函数里
    
    void TIM6_IRQHandler(void)
    {
        if(TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) 
        {	
            time++;                           // 每中断一次,time值加1,中断一次时间为1ms,需要中断1000次才可定时1s,即time值为1000
    	TIM_ClearITPendingBit(TIM6, TIM_FLAG_Update);  		 
        }		 	
    }
    

    最后在main()函数里调用led和定时器的初始化配置函数,在一个循环里判断time变量的值是否为1000,如果已经达到1000,则led灯状态变化(亮或灭)一次,并且time变量值重赋为0,以便继续判断及定时。

  • 相关阅读:
    用Python完成一个汇率转换器
    鸿蒙如何用JS开发智能手表App
    鸿蒙如何用JS开发智能手表App
    SAP Spartacus SplitViewComponent Migration 的一个具体例子
    SAP Spartacus B2B 页面 Popover Component 的条件显示逻辑
    SAP Spartacus 升级时关于 schematics 的更新
    SAP Spartacus B2B 页面 Disable 按钮的显示原理
    SAP Spartacus B2B 页面 Disable Confirmation 对话框的显示原理
    通过 Feature Level 动态控制 SAP Spartacus 的页面显示
    SAP Commerce Cloud Build Manifest Components
  • 原文地址:https://www.cnblogs.com/fire909090/p/8890971.html
Copyright © 2011-2022 走看看