现在有人有这样一个需求,他使用STM32F429芯片做开发,其中用到32位的TIM2实现3路PWM输出。
另外有上位机跟STM32的UART接口相连,上位机可能不定期地需要通过UART接口给STM32发送新的占空比参数,而且每次都发送3个比较输出通道的参数【12个字节】。
如何快捷地实现这个功能呢?要求收到数据后尽快修改3个比较通道的参数。
前一篇重点介绍了利用DMAFIFO和UART接收事件触发DMA传输实现了3个CCR寄存器的批量修改。
我们不妨就该话题稍作拓展,不再局限于某个STM32系列,而是从整个STM32的资源上考虑当前需求。上次提到3种实现方案,我想借此机会再给大家介绍另外一种实现方案,以拓宽未来解决类似问题的思路。
STM32 家族里有些系列是内置DMAMUX模块的,即DMA路由器,利用DMAMUX可以实现DMA请求与DMA传输通道的灵活配置;可以将一些通常不能直接产生DMA请求的事件通过它后而可以产生DMA请求;或者基于部分DMA完成事件产生新的DMA请求发起新的传输。目前,STM32家族中内置DMAMUX模块的系列有下面这些:
那么 我这里就利用DMAMUX的其中一个特性,即通过它可以让部分DMA完成事件产生新的DMA请求从而发起新的DMA传输。具体到这里,我们让UART 的DMA接收完成事件映射到DMAMUX的DMA generator,再申请新的DMA请求,让DMA将UART 接收到的数据从内存搬运到定时器的3个CCR寄存器,形成一个级联模式。大致流程是:
上位机数据 经UARTRX+DMA 接收到内存, 然后DMA 接收完成事件 经DMAMUX申请的新的DMA请求和 DMA通道,再将内存数据写到定时器的3个比较寄存器控制占空比。
下面我使用STM32G4系列芯片重点演示下实现过程,配置是关键。至于原理细节还请阅读相关手册。
我还是用UART1自发自收来模拟上位机发送新的CCR数据。
TIM2使用3个通道做PWM输出,使用CubeMx工具的参考配置如下:
我同样开启USART1的TX/RX事件的DMA传输功能。参考配置如下【注意UART RX DMA的配置与前一篇的差别】:
注意上图中的事件使能及DMA请求配置。接着看看下面关于DMA generator的相关配置:
请关注上图中所有配置。其中,DMAMUX生成的DMA请求由DMA2_CH2响应,工作在Circular模式。
我依然使用32位TxData【3】数组存放待传输的3个CCR值,用RxData[3]存放接收的数据。使用CubeMx配置完成后,添加相关用户代码。【基于HAL库组织代码】
我在UARTDMA接收完成中断的回调函数里对接收到新数据事件做标志更新。
为了便于演示,我依然在主程序里循环模拟远程命令,动态修改CCR寄存器的值。参考代码如下截图:
稍作调试我们就可以查看输出结果【借助断点实时查看内存和寄存器的数据】:
从上面贴图不难看出,从UART的发送数据、接收到的内存数据、寄存器的数据都在保持同步更新。
在上面演示过程中,我是将DMAMUX生成的新DMA请求申请的 DMA通道配置为Circular模式来着手测试的,如果配置为Normal模式也应该是可以的,只是需将Generator生成的新的DMA配置以及用户代码稍微做些调整,有兴趣的话可以自行测试验证。