STM32定时器输出4路不同频率的补充说明详解

参考该博主的文章,对该文档代码做补充说明:

STM32单片机一个定时器输出不同频率PWM波_利用定时器输出不同频率的pwm信号-CSDN博客

  1. 该博主的文章讲得非常不错,在他的基础上做一些补充以及自己的理解。

如何设置我们自己想要的频率呢?接下来这两个参数很关键

TIM_TimeBaseInitStructure.TIM_Period = arr;

TIM_TimeBaseInitStructure.TIM_Prescaler = psc;

首先先说一下psc这个参数,这个分频系数确定之后,最大计数值arr也就定了。举个例子:

假设:psc是72   那么最大计数值

arr  =  72 000 000  /  72 = 1000 000

理论上arr = 1000 000 但是我们从资料上查找计数器是一个16位的计数器,最大值只能为65536。

 

如果:psc 为 7200 

arr  =  72 000 000  /  7200 = 10000

那么arr 计数最大为10000,计数值并没有超出65536。

PSC的范围是1~65536

理解了这一部分之后,我们来看代码:

这里的PSC = 0  STM32芯片会自动加1,所以分频系数为1,也就是说不分频。然后

arr  =  72 000 000 /  1  =  72 000 000

(也就是说1秒钟可以计72 000 000个数)

但是arr 只能为65535,原因上面已经说了。那么我们可以算出计一个数的时间:

 1 / 72 000 000  约等于13.8ns。

根据我们设定的比较值

也就可以算出对应的时间:

CCR1_Val = 32768 

对应的周期是  32768 x 13.8 = 455 111.111ns = 455.111us

CCR2_Val = 16384

对应的周期是  16384 x 13.8 = 226.099us

CCR3_Val = 8192

对应的周期是  8192 x 13.8 = 113.049us

CCR3_Val = 4096

对应的周期是  4096 x 13.8 =56.524us

也就是下面的周期(如图所示):

上面的波形是占空比设定了

以上是对博主的代码解读, 有解读不对的地方请指正。

    

     根据上面的计算,我们能设置的最慢是时间是
      13.8 x 65536 = 904.396us。往往这个时间太快了,不是我们所需要的。接下来是我在博主基础上更改的参数:

1、本人使用的是定时器4

/* Time base configuration */

TIM_TimeBaseStructure.TIM_Period    = TIM4_Period;

TIM_TimeBaseStructure.TIM_Prescaler = TIM4_Prescaler;

TIM_TimeBaseStructure.TIM_ClockDivision = 0;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

TIM4_Period    设置的是 10000 – 1 

TIM4_Prescaler 设置的是 7200 – 1  72000000 / 7200 = 10000 此时计数值最大是10000

从而算出记一个数所需要的时间是  1s / 10000 = 100us

设定的比较值

u16 CCR1_Val = 5000;

u16 CCR2_Val = 2500;

也就可以算出对应的时间:

CCR1_Val = 5000

对应的周期是  5000 x 100us= 500ms

CCR1_Val = 2500

对应的周期是  2500 x 100us= 250ms

如下图所示,黄色线与绿色线

需要注意的是:红色标注是需要添加的,不然输出的频率会不对

//占空比 0 — 100

 u16 CCR1_dc = 50;

 u16 CCR2_dc = 50;

 u32 capture = 0;

 u8 flag1 = 0,flag2 = 0,flag3 = 0,flag4 = 0;//标志位

 u16 setcap = 0;

 void TIM4_IRQHandler( void )

 {

             

   if( TIM_GetITStatus( TIM4, TIM_IT_CC1 ) != RESET )

     {

         TIM_ClearITPendingBit( TIM4, TIM_IT_CC1 );

         capture = TIM_GetCapture1( TIM4 );    //获取输入捕获比较器 1 的值  

        //设置占空比

         if( flag1 == 0 )

        {

             flag1 = 1;

             setcap = capture + ( u32 )CCR1_Val * CCR1_dc / 100;

         }

         else

        {

             flag1 = 0;

             setcap = capture + ( u32 )CCR1_Val  * ( 100 – CCR1_dc ) / 100;

         }

                           

                             if(setcap > TIM4_Period)

                             {

                                    setcap %= TIM4_Period  + 1;

                             }

                           

         TIM_SetCompare1( TIM4, setcap);

     }

               

               if( TIM_GetITStatus( TIM4, TIM_IT_CC2 ) != RESET )

     {

         TIM_ClearITPendingBit( TIM4, TIM_IT_CC2 );

         capture = TIM_GetCapture2( TIM4 );    //获取输入捕获比较器 1 的值  

        //设置占空比

         if( flag2 == 0 )

        {

             flag2 = 1;

             setcap = capture + ( u32 )CCR2_Val * CCR2_dc / 100;

         }

         else

        {

             flag2 = 0;

             setcap = capture + ( u32 )CCR2_Val  * ( 100 – CCR2_dc ) / 100;

         }

                           

                             if(setcap > TIM4_Period)

                             {

                                    setcap %= TIM4_Period  + 1;

                             }

                           

         TIM_SetCompare2( TIM4, setcap);

     }

   

 }

解读:

因为setcap累加会超出TIM4_Period(也就是10000),超出时需要给它取余。

if(setcap > TIM4_Period)

 {

      setcap %= TIM4_Period  + 1;

// 加1是因为TIM4_Period设置的是10000 – 1,如果这句不理解。把TIM4_Period  + 1 改成10000

}

物联沃分享整理
物联沃-IOTWORD物联网 » STM32定时器输出4路不同频率的补充说明详解

发表评论