当前位置 博文首页 > 文章内容

    STM32定时器(TIM1、TIM2、TIM3、TIM4、TIM5、TIM8)高级定时器+普通定时器,配置使用

    作者: 栏目:未分类 时间:2020-08-17 9:01:37

    本站于2023年9月4日。收到“大连君*****咨询有限公司”通知
    说我们IIS7站长博客,有一篇博文用了他们的图片。
    要求我们给他们一张图片6000元。要不然法院告我们

    为避免不必要的麻烦,IIS7站长博客,全站内容图片下架、并积极应诉
    博文内容全部不再显示,请需要相关资讯的站长朋友到必应搜索。谢谢!

    另祝:版权碰瓷诈骗团伙,早日弃暗投明。

    相关新闻:借版权之名、行诈骗之实,周某因犯诈骗罪被判处有期徒刑十一年六个月

    叹!百花齐放的时代,渐行渐远!



    2.1    时钟来源

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

    ·内部时钟(CK_INT)

    ·外部时钟模式1:外部输入脚(TIx)

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

           ·内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时器Timer1而作为另一个定时器Timer2的预分频器。

        由于今天的学习是最基本的定时功能,所以采用内部时钟。TIM2-TIM5的时钟不是直接来自于APB1,而是来自于输入为APB1的一个倍频器。这个倍频器的作用是:当APB1的预分频系数为1时,这个倍频器不起作用,定时器的时钟频率等于APB1的频率(36MHZ);

    当APB1的预分频系数为其他数值时(即预分频系数为2、4、8或16),这个倍频器起作用,定时器的时钟频率等于APB1的频率的2倍。

    {       

            假如APB1预分频为2(变成36MHZ),则定时器TIM2-5的时钟倍频器起作用,将变成2倍的APB1(2x36MHZ)将为72MHZ给定时器提供时钟脉冲。 一般APB1和APB2的RCC时钟配置放在初始化函数中例如下面的void RCC_Configuration(void)配置函数所示,将APB1进行2分频,导致TIM2时钟变为72MHZ输入。

    如果是1分频则会是36MHZ输入,如果4分频:CKINT=72MHZ/4x2=36MHZ;  8分频:CKINT=72MHZ/8x2=18MHZ;16分频:CKINT=72MHZ/16x2=9MHZ 

       }

    //系统时钟初始化配置
    void RCC_Configuration(void)
    {
        //定义错误状态变量
       ErrorStatus HSEStartUpStatus;
       //将RCC寄存器重新设置为默认值
       RCC_DeInit();
       //打开外部高速时钟晶振
       RCC_HSEConfig(RCC_HSE_ON);
       //等待外部高速时钟晶振工作
       HSEStartUpStatus = RCC_WaitForHSEStartUp();
       if(HSEStartUpStatus == SUCCESS)
       {
              //设置AHB时钟(HCLK)为系统时钟
              RCC_HCLKConfig(RCC_SYSCLK_Div1);
              //设置高速AHB时钟(APB2)为HCLK时钟
              RCC_PCLK2Config(RCC_HCLK_Div1);
              //设置低速AHB时钟(APB1)为HCLK的2分频(TIM2-TIM5输入TIMxCLK频率将为72MHZ/2x2=72MHZ输入)
              RCC_PCLK1Config(RCC_HCLK_Div2);
              //设置FLASH代码延时
              FLASH_SetLatency(FLASH_Latency_2);
              //使能预取指缓存
              FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
              //设置PLL时钟,为HSE的9倍频 8MHz * 9 = 72MHz
              RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
              //使能PLL
              RCC_PLLCmd(ENABLE);
              //等待PLL准备就绪
              while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
              //设置PLL为系统时钟源
              RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
              //判断PLL是否是系统时钟
              while(RCC_GetSYSCLKSource() != 0x08);
       }
       //允许TIM2的时钟
       RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
       //允许GPIO的时钟
       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    }

    三、定时器代码实例

     中断优先级就不贴出来了,自己可以配置下

     Tout= ((arr+1)*(psc+1))/Tclk;

    arr:计数重装值,psc分频数,Tclk系统时钟频率,Tout一个周期的时间。

     Tout= ((arr+1)*(psc+1))/Tclk;

     3.1、定时器1使用

    这里假设APB2时钟是1分频即72MHZ(如果是4分频则为36MHZ [=72MHZ/4x2=36MHZ] )配置,void RCC_Configuration(void)中配置如下代码:

    1           //设置高速AHB时钟(APB2)为HCLK时钟
    2           RCC_PCLK2Config(RCC_HCLK_Div1);

    则这里:APB2的时钟为1分频故出来的APB2时钟还是72MHZ,TIM1对系统时钟APB2(72MHZ)再进行7200分频,然后计数重载初值设置为100,则一个定时周期Tout=(100-1+1)*(7200-1+1)/72,000,000=1/10=0.1s,即100ms为一个计数周期

    1 //放到主函数的初始化中初始化
     2 void Timer1CountInitial(void)
     3 {
     4     //定时=36000/72000x2=0.001s=1ms;
     5         TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;
     6         ///////////////////////////////////////////////////////////////
     7         RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
     8         
     9         TIM_TimeBaseStructure.TIM_Period = 100-1;//自动重装值(此时改为100ms)
    10         TIM_TimeBaseStructure.TIM_Prescaler = 7200-1;//时钟预分频
    11 //        TIM_TimeBaseStructure.TIM_Prescaler = 36000-1;//时钟预分频
    12         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
    13 //        TIM_TimeBaseStructure.TIM_Period = 2-1;//自动重装值
    14 //        TIM_TimeBaseStructure.TIM_Period = 10-1;//自动重装值(此时改为10ms)
    15         TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;        //时钟分频1
    16         TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;            
    17         TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);
    18         
    19         TIM_ClearFlag(TIM1,TIM_FLAG_Update);
    20         TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);  
    21         TIM_Cmd(TIM1, ENABLE);
    22 }
    23 
    24 
    25 void TIM1_UP_IRQHandler(void)
    26 {        
    27     //TIM_TimeBaseStructure.TIM_Period = 100-1;//自动重装值(此时进中断的周期为100ms)
    28     if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)
    29     {  
    30         //添加行程开关去抖程序
    31         if(XingChengTickNum_QuFantan<1000)//
    32         {
    33             XingChengTickNum_QuFantan++;
    34         }             5455     TIM_ClearITPendingBit(TIM1,TIM_IT_Update);58 }

    3.2、定时器2使用

     Tout= ((arr+1)*(psc+1))/Tclk;

    arr:计数重装值,psc分频数,Tclk系统时钟频率,Tout一个周期的时间。

    假设APB1时钟是2分频即72MHZ(如果是1分频则为36MHZ)配置,void RCC_Configuration(void)中配置如下代码:

    //设置低速AHB时钟(APB1)为HCLK的2分频(TIM2-TIM5输入TIMxCLK频率将为72MHZ/2x2=72MHZ输入)
     RCC_PCLK1Config(RCC_HCLK_Div2);

    这里:APB1的时钟为分频故出来的APB2时钟还是72MHZ,TIM1是对系统时钟APB2(72MHZ)进行7200分频,

    则:Tout=(4-1+1)*(36000-1+1)/72,000,000=4/2,000=2ms

    void TIM2_Int_Init(void)
    {
        TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    
        TIM_DeInit(TIM2);
    
        TIM_TimeBaseStructure.TIM_Period = 4 - 1;//2000 - 1;
        TIM_TimeBaseStructure.TIM_Prescaler = (36000 - 1);
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    
        TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    
        TIM_ClearFlag(TIM2, TIM_FLAG_Update);
        TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    
        TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    
        TIM_Cmd(TIM2, ENABLE);
    }
    void TIM2_IRQHandler(void)
    {
    
        if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
        {
                    interrupt_rtc();//可以使你自己定义的执行函数
        }
         TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update);
    }

    3.3、定时器3使用

     假设APB1时钟是2分频即72MHZ(如果是1分频则为36MHZ)配置,void RCC_Configuration(void)中配置如下代码:

    1           //设置低速AHB时钟(APB1)为HCLK的2分频(TIM2-TIM5输入TIMxCLK频率将为72MHZ/2x2=72MHZ输入)
    2           RCC_PCLK1Config(RCC_HCLK_Div2);
    TIM3_Int_Init(4-1,36000-1);

    则:Tout=(4-1+1)*(36000-1+1)/72,000,000=4/2,000=2ms

    //通用定时器3中断初始化
    //这里时钟选择为APB1的2倍,而APB1为36M
    //arr:自动重装值。
    //psc:时钟预分频数
    //这里使用的是定时器3!
    void TIM3_Int_Init(u16 arr,u16 psc)
    {
      TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
    
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
    
        TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值     计数到5000为500ms
        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率
        TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
    
        TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
    
        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_InitStruct中指定的参数初始化外设NVIC寄存器
    
        TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设
    
    }
    //定时器3中断服务程序
    void TIM3_IRQHandler(void)   //TIM3中断
    {
        if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
            {
            TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源
            LED1=!LED1;
            }
    }

    3.4、定时器4使用

     假设APB1时钟是4分频即72/4=18MHZ(如果是4分频则TIMxCLK=18MHZx2=36MHZ)配置,void RCC_Configuration(void)中配置如下代码:

    1 //在void RCC_Configuration(void)中配置APB1时钟4分频或1分频都变为36MHZ
    2 //设置低速AHB时钟(APB1)为HCLK的4分频(TIM2-TIM5输入TIMxCLK频率将为72MHZ/4x2=36MHZ输入)
    3 RCC_PCLK1Config(RCC_HCLK_Div4);//加入使用4分频
    TIM4_Int_Init(4-1,36000-1);

    则:Tout=(4-1+1)*(36000-1+1)/36,000,000=4/1,000=4ms

    void TIM4_Int_Init(u16 arr,u16 psc)
    {
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
    
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //时钟使能
        //定时器TIM4初始化
        TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
        TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
        TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM4中断,允许更新中断
    
        //中断优先级NVIC设置
        NVIC_InitStructure.NVIC_IRQChannel = TIM4_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(TIM4, ENABLE); //使能TIMx
    }
    
    
    //定时器4中断服务程序
    void TIM4_IRQHandler(void) //TIM3中断
    {
        if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) //检查TIM4更新中断发生与否
        {
            TIM_ClearITPendingBit(TIM4, TIM_IT_Update ); //清除TIMx更新中断标志
            LED0=!LED0;
            // Get_Angle();
        }
    }

    3.5、定时器5使用

    假设APB1时钟是1分频即36MHZ(如果是1分频则TimexCLK=36MHZx1=36MHZ)配置,void RCC_Configuration(void)中配置如下代码:

    1 //在void RCC_Configuration(void)中配置APB1时钟4分频或1分频都变为36MHZ
    2 //设置低速AHB时钟(APB1)为HCLK的4分频(TIM2-TIM5输入TIMxCLK频率将为72MHZ/4x2=36MHZ输入)
    3 RCC_PCLK1Config(RCC_HCLK_Div1);//假如使用1分频
    TIM5_Int_Init(4-1,36000-1);

    则:Tout=(4-1+1)*(36000-1+1)/36,000,000=4/1,000=4ms

    void TIM5_Init(u16 arr,u16 psc)
    {
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
    
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //时钟使能
    
        TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值     计数到5000为500ms
        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率
        TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
    
        TIM_ITConfig(TIM5,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
    
        NVIC_InitStructure.NVIC_IRQChannel = TIM5_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_InitStruct中指定的参数初始化外设NVIC寄存器
    
        TIM_Cmd(TIM5, ENABLE);  //使能TIMx外?
    }
    //定时器5中断服务程序
    void TIM5_IRQHandler(void)   //TIM3中断
    {
        if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
            {
            TIM_ClearITPendingBit(TIM5, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源
            LED1=!LED1;
            }
    }