查看原文
其他

利用定时器比较输出切换实现定制波形示例

MilerShao 茶话MCU 2022-09-10

有人想实现如下图所示的PWM输出波形,周期T=12us,两路输出波形特征一样,只是第2路【下面那路】波形的输出比第1路【上面那路】滞后T/2。另外,还要保证二者占空比在0~50%范围内可以同步调节。

对于这种输出波形,如果使用2个定时器来做就会相对方便些,通过定时器的主从模式来实现。现在客户希望使用1个定时器来完成,那如何实现呢?

当然,用1个带多比较通道的STM32常规定时器也是可以实现的。我们可以使用PWM输出模式来实现第1路,使用比较输出切换模式来实现第2路。对于第2路的关键是适时给出正确的比较值来完成比较切换输出。下面以STM32F334的开发板来进行相关设置、调试、验证。


不妨选TIM3实现该输出波形。TIM3的时钟源目前配置为64Mhz,不做预分频,使用向上计数模式。一个计数周期对应的ARR是(12*64)-1,即767。TIM3的通道1对应下面波形的第1路,TIM3的通道3对应下面波形的第2路.【图中的橙色斜箭头表示计数器计数变化趋势,从0到ARR,并周期性循环计数。】


因为TIM3通道1采用PWM模式来输出,只需设置好CCR1、ARR的值即可。对于通道3,采用比较输出切换模式来实现,那么它在一个周期内有两个翻转点,即上图中第2路上升沿的R点和下降沿的F点。结合本实例需求,不难得知,R点所对应的比较值【CCR3】为768/2,即384并且保持不变。F点所对应的比较值大小决定其占空比。由于这里实际需求的占空比不超过50%,正常来讲,则F点可以设置的比较值最大不会超过ARR的值。


我们借助TIM3_CH3的比较事件触发DMA,通过DMA来传输存储在内存中R点/F点所对应的比较值以更新CCR3寄存器内容。在R点发生比较事件时,更新F点的比较值,在F点发生比较事件时更新R点的比较值。刚才前面说过了,这里R点的比较值始终保持不变,即384,我们通过改变F点的比较值来改变TIM3通道3的占空比。

对于2个通道占空比的调整,我是通过在TIM3通道1的比较中断里同时修改CCR1的值和通道3在F点所对应的CCR3比较值,最终实现2路占空比0~50%灵活可调的输出。


大致原理就介绍到这里。下面开始基于STM32CubeMx进行配置。初始脉宽设置200个时钟单位。其中,有关RCC/SYS等配置这里从略,不附截图了。

1、关于定时器TIM3的基本时基参数配置如下:

2、基于定时器事件的DMA传输配置如下:

有关NVIC的配置可以按需操作,其中DMA的传输中断CubeMx工具已默认帮我们开启。这里还开启了TIM3相关的NVIC配置。将来我们要在TIM3的OC1比较中断里修改CCR1与通道3下降沿翻转点(即上文中的F点)所对应的比较值,即CCR3的值。

3、在CubeMx环境下完成各项配置后,即可生成包含初始化配置代码的工程。

4、在新建的工程里,添加用户代码。

4.1 开启TIM3 CCR1的预装功能。

__HAL_TIM_ENABLE_OCxPRELOAD(&htim3,TIM_CHANNEL_1);

4.2 关闭TIM3 CCR3的预装功能。

__HAL_TIM_DISABLE_OCxPRELOAD(&htim3,TIM_CHANNEL_3);

4.3 使能TIM3 通道1的比较输出中断。   

__HAL_TIM_ENABLE_IT(&htim3, TIM_IT_CC1);    

4.4 使能TIM3 通道1的比较输出功能。

TIM_CCxChannelCmd(TIM3, TIM_CHANNEL_1,TIM_CCx_ENABLE);

4.5 使能TIM3 通道3的比较输出及DMA传输功能。

HAL_TIM_OC_Start_DMA(&htim3, TIM_CHANNEL_3,Data_Pwm,2);

其中,Data_Pwm是为DMA传输定义的一个内存数组名。

初始定义是:uint32_t Data_Pwm[]={584,384};

4.6 启动TIM3的计数器工作。

__HAL_TIM_ENABLE(&htim3);

4.7 在TIM3的OC1比较中断里修改CCR1和通道3下降沿翻转点所对应的比较值。

具体代码放在中断里调用的回调函数。

5、编译、运行,验证结果。

我这里借助MDK-IDE自带的模拟逻辑分析仪,可以看到预期的结果。两路波形保持固定相差,占空比在0~50%范围同步变化。下面是动态过程中的两幅截图,供参考。【红色波形是通道1使用PWM模式实现的,绿色的是通道3使用比较切换模式实现的。】

小结下:

利用定时器的比较输出切换模式,结合DMA外设,可以灵活地输出各种自定义波形。另外,STM32常规定时器中的CCR寄存器跟ARR寄存器一样具有预装功能,什么时候需开启什么时候需要关闭,需结合具体应用来正确配置。否则,在更新ARR/CCR寄存器内容时,可能输出一些我们不期望的脉冲出来,比方不时产生些类似于干扰的尖而窄的脉冲。

看到这里,或许有人会问,上面在使用TIM3的CH1/CH3来实现上述输出时,为何跳过CH2呢?是出于配置时随手选择还是有意跳过CH2?

另外,在上面添加用户代码,针对CCR1/CCR3的预装功能配置时,怎么不一样?为什么?

关于上面两个问题,可以结合上面内容、stm32手册自行思考下。


最后,顺便解释下上篇《多个ADC模块同时采样转换的应用示例》最后结果为什么是00,00,00,fff,fff,fff,而不是00,fff,00,fff,00,fff的问题。

现在是3个ADC模块,每个ADC使用2个AD通道。3个ADC模块做同时采样转换,扫描式完成。采样转换是按照下图顺序进行,先第一列,后第二列。这里第一列的3个通道都是接GND,第2列的3个通道都是接VDD,所以最后结果是00,00,00,fff,fff,fff.



往期话题链接:

1、多个ADC模块同时采样转换的应用示例

2、STM32的TIM+DMA+DAC应用示例

3、STM32开发者的免费福利---TouchGFX

4、单片机调试过程中的第3只眼

5、IAR环境下从CCM RAM执行程序的介绍

              



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存