我有一台STM32F4,我想要用一个掩码PWM一个GPIO端口。
所以,也许我们想要在200khz下暂时PWM 0b00100010
,但是,10khz之后,我们现在想要PWM 0b00010001
...然后,10kHz之后,我们想要PWM其他一些掩码在同一个GPIO上。
我的问题是,你如何用DMA做到这一点?我尝试触发DMA传输,将所有位设置为上升沿,然后是另一个DMA传输,将在下降沿清除所有位。
我还没有找到一个很好的方法来做到这一点,(至少在CubeMX以及我对C& STM32&s的经验有限),因为看起来我只有机会做一些事情。上升的边缘。
我主要担心的是CPU时间,因为虽然我在上面的例子中提到了数百千赫兹,但我还是希望这个框架非常强大,因为它不会浪费CPU资源......这就是为什么我喜欢DMA的想法,因为它的专用硬件在这里做了一个单词的无意义的提取,有一种类型的东西,而CPU可以做其他的像PID或其他东西的紧缩数字。
修改 为清楚起见:我有一组6个值可以写入GPIO。它们存储在一个数组中。 我想要做的是设置一个PWM定时器,在PWM的正宽度期间设置GPIO,然后我希望GPIO在低周期宽度期间设置为0b00000000(如果是pwm)。 因此,我需要查看上升沿的时间,快速写入gpio,然后查看下降沿的时间,并将0写入gpio。
答案 0 :(得分:2)
有限解决方案没有DMA
STM32F4控制器有12个定时器,每个定时器最多有4个PWM通道,总共32个。它们中的一些可以同步以一起开始,例如,您可以TIM1
同时开始TIM2
,TIM3
,TIM4
和TIM8
。这是20个同步PWM输出。如果它还不够,你可以形成链子,其中从属计时器是另一个的主人,但保持所有这些完全同步是非常棘手的。如果可以接受几个时钟周期的偏移,那就不那么棘手了。
STM32CubeF4库示例项目部分中有几个示例,您可以从中集中设置,查看Projects/*_EVAL/Examples/TIM/*Synchro*
。
一般解决方案
当计数器达到重载值(更新事件)和时,通用或高级计时器(除TIM6
和TIM7
之外的所有计时器都可以触发DMA传输) strong>当计数器等于任何比较值(捕获/比较事件)时。
想法是让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个引脚。也许第3频道。
您仍然可以使用TIM2
,TIM3
,TIM4
和TIM5
(每个都可以从属TIM1
或TIM8
)另外16个PWM输出,如我帖子的第一部分所述。如果您能找到合适的主从设置,也可以TIM9
和TIM12
,还有4个。
这是90个引脚同时切换。注意总电流限制。
答案 1 :(得分:0)
PWM 0b00100010是什么意思? PWM是具有一定占空比的方波。使用DMA存档非常困难,但您需要具有已计算值的表。例如,为了具有10%比率的2kHz PWM,您将需要具有10个样本,其中一个具有位设置,9个具有位归零。您可以将定时器配置为20k / sec触发mem-to-mem(GPIO必须以这种方式完成)以循环模式进行DMA传输。在引脚上你将有2kHz 10%的波形。 PWM分辨率为10%。如果你想把它设为0.5%,你需要200个样本表,DMA每秒触发400k次。
IMO最好使用定时器和DMA为其加载新值(请参阅参考手册中定时器文档中的突发DMA模式)