STM32主从定时器实现可变频率、相位与占空比PWM输出的实践指南(亲测有效)

#一、程序需求

        使用STM32输出两路PWM信号,CH1与CH2要求频率相同,占空比和相位差独立可调,并且能够根据上位机命令动态更改频率、占空比和相位,PWM频率要求至少50k。因此,STM32的主函数需要接收上位机消息并进行处理,如果用写IO口高低电平时序的方法,会使输出PWM信号不连续,因此只能使用定时器的方式实现。

#二、尝试过的方法

##2.1 使用两个定时器,两个定时器的输出时间有延时

        我最开始的想法非常简单,只要配置好定时器,在第一个定时器输出后再delay一段时间,不就有相位差了吗?事实证明这是行不通的,这样子发出来的PWM信号,CH1和CH2虽然输出的时间上有先后,但是它们的相位是完全一致的!

##2.2 使用定时器比较输出,并在定时中断中更改CCR值

        经过一番搜索后,我成功找到了一个可行的方法,也就是下面列出来的这个博客,里面非常详细地讲解了定时器比较输出模式的原理。他提出用定时比较输出的方式,并在中断中更改CCR值,可以生成可变频率、占空比、相位的PWM波。他的方法基本可行,但是占空比好像只能大于50%,并且我试过的最高频率只有10k,无法再高频。我猜测是定时器的速度太快,而处理中断需要CPU,当频率高了之后,进入和跳出中断需要的时间无法减少,还来不及进入中断处理函数,定时器的下一个溢出信号又发生了,因此导致这种方法无法适用于高频的场景。这仅是我的猜想,不知道有没有大神使用这种方法输出过几十k的PWM?https://blog.csdn.net/That_Assassin/article/details/135394480https://blog.csdn.net/That_Assassin/article/details/135394480#2.3 使用主从定时器,主定时器的溢出信号延时启动(不复位)从定时器

        这个方法相比与之前的方法,不需要使用中断,可以达到高频率,并且可以任意调节占空比,但是这个方法无法动态地更改频率,而是只能在初始化的时候设定好主从定时器的启动延时,之后便无法再更改。其实,发出不同相位的PWM波,本质上就是使两个定时器发出PWM波具有一定的时间差,只不过2.1中的方法看似使用delay延时,实际上如果不采用主从定时器的方法,默认条件下,不同定时器输出的PWM波相位仍然是同步的。下面我简单地介绍一下这种方法。他发生两路PWM共使用了3个定时器,第一个定时器TIM1用于输出一定频率和占空比的PWM波,作为CH1,第二个定时器TIM2作为主定时器,它是与TIM1同相位的。第三个定时器TIM3,它的启动受TIM2的溢出信号控制,它发出的PWM波作为CH2。因此,只需改变TIM2的ARR值,便可改变TIM2与TIM3的相位,也就是TIM1与TIM3的PWM相位。

https://blog.csdn.net/m0_58944197/article/details/138513190https://blog.csdn.net/m0_58944197/article/details/138513190#三、最终亲测有效的方法

#3.1 使用主从定时器,主定时器的溢出信号延时复位从定时器

        这个方法结合了2.2和2.3中提到的方法,他既使用了比较输出模式实现PWM移相效果,还使用了主从定时器用于同步相位。下面我先简单说一下实现的步骤,首先令TIM1的channel1输出一定频率和占空比的PWM波,作为CH1,之后令TIM1的channel2使用比较输出模式,输出与CH1有一定相位差的PWM,这一相位差可通过设置TIM1的channel2的CCR值改变,之后,设置TIM1为主定时器,触发事件输出(TRGO)选择channel2的OC2REF,最后,设置TIM2为从定时器,从模式选择RestMode,并且输出与CH1相同频率,占空比不同的PWM波,因此CH2与TIM1的channel2同相,而TIM1的channel1与channel2有一定相位差,最终实现CH1与CH2具有可调的相位差,并且占空比可以独立调节,频率可以改变。

具体配置如下:

        从图中可以看到TIM1的配置,channel1为PWM Generation,channel2为Output Compare。TIM1的PSC为24-1,我的主频为24M,经过PSC的预分频变为1M。TIM1的ARR为100-1,这意味着初始的PWM频率为1M/100,也就是10K。

        紧接着上面,注意红框内的设置,这些设置保证了TIM1作为主定时器(Enable),并且说明了触发事件为通道2的output compare(OC2REF)

        往下拉,在这个选项框,PWM mode1为默认,Pulse也就是CCR,我们让它为10。也就是channel1的频率为10k(由ARR决定,前面说过),占空比为CCR/ARR(10/100),也即是10%。对于channel2的设置,选择Toggle on match,也就是CNT=CCR时翻转,因此channel2的频率为5k,对于Pulse也就是CCR,我们令他为30,对于ARR=100的情况下,频率为10k,周期也就是100us,CCR=30的话就是延时CCR/ARR*100us,也就是30%*100us,即30us。

        快要成功了,让我们选中到TIM2,Slave Mode为Reset Mode,Trigger Source选择ITR0,它表明触发源为TIM1,如果想用其他的从定时器和主定时器,可以参考下面的图片,Clock Source选disable,意为仅使用TIM1作为触发,下面的24-1和100-1目的是频率和CH1一样也是10K,至于TRGO,因为是从定时器,直接disable。再往下拉设置Pluse为10,也就是10%占空比,与前面同理。

        想用其他从定时器的,它的触发源如何选择对应着不同的主定时器,是从STM32中文使用手册中截取的。

主函数中启动即可,注意主从定时器启动,先初始化主定时器,之后从定时器

最终效果如图,正如我们设置的那样

作者:兵者,诡道也

物联沃分享整理
物联沃-IOTWORD物联网 » STM32主从定时器实现可变频率、相位与占空比PWM输出的实践指南(亲测有效)

发表回复