tes*_*123 2 arm stm32 dma gpio pwm
我有一个 STM32F4,我想对一个已与掩码进行“或”运算的 GPIO 端口进行 PWM 处理。
因此,也许我们想要以0b00100010200khz 进行一段时间的 PWM,但是,10khz 后,我们现在想要进行 PWM 0b00010001...然后,10kHz 后,我们想要在同一 GPIO 上对其他一些掩码进行 PWM。
我的问题是,如何使用 DMA 做到这一点?我正在尝试触发一个 DMA 传输,该传输将在上升沿设置所有位,然后触发另一个 DMA 传输,该传输将在下降沿清除所有位。
我还没有找到一个好的方法来做到这一点(至少使用 CubeMX 以及我对 C 和 STM32 的有限经验),因为看起来我只有机会在上升沿做一些事情。
我主要关心的问题之一是 CPU 时间,因为尽管我在上面的示例中提到了数百千赫兹,但我想让这个框架非常强大,因为它不会浪费 CPU 资源。这就是为什么我喜欢 DMA 的想法,因为它是专用硬件,可以无意识地将这里的一个单词提升到那里的一个单词之类的东西,而 CPU 可以做其他事情,比如处理 PID 的数字或其他东西。
编辑 为了清楚起见:我有一组 6 个值,可以写入 GPIO。它们存储在一个数组中。我想要做的是设置一个 PWM 定时器来在 PWM 的正宽度期间设置 GPIO,然后我希望在低周期宽度期间将 GPIO 设置为 0b00000000(如果 pwm. 因此,我需要查看上升沿何时,快速写入GPIO,然后查看下降沿何时,并向GPIO写入0。
没有 DMA 的有限解决方案
STM32F4 控制器有 12 个定时器,每个定时器最多有 4 个 PWM 通道,总共 32 个。其中一些可以同步一起启动,例如您可以TIM1启动TIM2, TIM3,TIM4TIM8同时和。这是 20 个同步 PWM 输出。如果这还不够,您可以形成一个从属计时器是另一个计时器的主计时器的链,但要保持所有计时器完全同步是相当棘手的。如果几个时钟周期的偏移是可以接受的,那么就不那么棘手了。
STM32CubeF4 库示例项目部分中有几个示例,您可以从中拼凑出您的设置,请查看Projects/*_EVAL/Examples/TIM/*Synchro*.
通用解决方案
当计数器达到重载值(更新事件)时,通用或高级定时器(除了TIM6和之外的所有定时器)可以触发 DMA 传输TIM7计数器等于任何比较值(捕获/比较事件)时,
这个想法是让 DMA 将所需的位模式写入BSRR比较事件的低(设置)一半,并将相同的位写入高(重置)一半BSRR更新事件的高(重置)一半。
但存在一个问题,即根本DMA1无法访问 GPIO 寄存器所连接的 AHB 总线(参见参考手册中的图 1 或图 2)。因此我们必须使用DMA2, 这给我们留下了高级计时器TIM1或TIM8。事情变得更加复杂,因为由这些定时器的更新和比较事件引起的 DMA 请求最终会出现在不同的 DMA 流上(请参见 RM 中的表 43)。为了使其更简单,我们可以使用 DMA 2、Stream 6 或 Stream 2、Channel 0,它们组合了来自 3 个计时器通道的事件。我们可以将一个定时器通道上的比较寄存器设置为 0,而不是使用更新事件。
设置所选定时器的 DMA 流
GPIOx->BSRR现在,设置计时器
这样,每个定时器可以控制 16 个引脚,如果在主从模式下使用它们,则可以控制 32 个引脚。
要同时控制更多引脚(最多 64 个),请为通道 4 比较和定时器更新事件配置附加 DMA 流,将数据项数量设置为 1,并用作((uint32_t)&GPIOx->BSRR)+2更新流的外设地址。
通道 2 和 4 可用作常规 PWM 输出,从而为您提供了 4 个以上的引脚。也许第三频道也是如此。
您仍然可以使用TIM2、TIM3、TIM4和TIM5(每个都可以从属于TIM1或TIM8)获得另外 16 个 PWM 输出,如我的文章第一部分所述。如果您能找到合适的主从设置,也许还有 4 个以上TIM9。TIM12
即有 90 个引脚同时切换。注意总电流限制。
| 归档时间: |
|
| 查看次数: |
4747 次 |
| 最近记录: |