单片机学习小组
直播中

刘芳

7年用户 1311经验值
私信 关注

使用3个PWM-DMA控制多个2000+WS2812灯会出现哪些问题呢

使用3个PWM-DMA控制多个2000+WS2812灯会出现哪些问题呢?如何去解决这些问题呢?

回帖(1)

陶珪扁

2022-2-11 09:28:14
STM32F405 多路DMA+PWM方式控制2000+WS2812灯优化buffer占用flash空间不足问题

前面已经实现了使用3个PWM-DMA控制1000多个灯(STM32F4 多路DMA PWM控制千颗灯初始化),那么想要控制更多的灯的时候问题来了:
1、DMA Buffer过大导致flash空间不足的问题


编译链接时报错 该报错通常是RAM或ROM不足
那么整个程序最耗费空间的地方其实在这里

这里的四个变量是DMA传输buffer,(这里占用大小只和总灯珠数[4*SK6812_SIZE]有关,和用几路PWM分别控制是无关的,这里分多路控制是设备硬件原因以及为了时分复用刷新),类型是u32的原因是TIM2 CCR寄存器是32位的,为了使用DMA时与其保持字宽一致,所以Buffer也是32位的,如果想在不影响其他应用的情况下控制更多SK6812/WS2812,就需要对其做出优化。
2、尝试将DMAbuffer设置为8位以减小空间占用

DMAbuffer实际对控制有效位数只有低8位(因为一码PWM ARR寄存器值为3,零码为1,高位全是0),那我可不可以将Buffer设置为8位大小,用DMA去填充32位CCR寄存器呢(即MSIZE=8),先做一个测试,将DMAbuffer、DMA传输字宽都设置为8位,将buffer设置为{1,2,3,4}看看传输结果。
测试结果:

测试结果如上,可见DMA每次都将4个同样的8位数均匀填充至32位CCR中,显然,这个结果不是我们想要的,我们想要的效果是:0x04(DMABuffer)–DMA传输–0x00000004(CCR1)
查阅datasheet有关DMA在字节宽度不同时的说明

可见当内存(变量)端口宽度小于外设端口宽度时,其高位采用重复填充/组合填充的方式。这个手册写死了,因此无法通过配置来解决这个问题。为了保证数据完整一致,在STM32F4上DMAbuffer必须与外设端口宽度一致,32位点的TIM就对应32位Buffer(个人感觉ST设计的没有那么完善,F1的DMA就能自动高位补0,见下图)
3、更换低位数TIM间接减小DMAbuffer空间占用

前面已经验证过,STM32上DMABuffer需与TIM端口一致,那么将原先32位的TIM换成16位的TIM也能间接减小DMAbuffer大小(DMAbuffer就可以初始化为16位了)

这里选用TIM3+TIM2定时器,通道选择TIM3-CH1,2,3,4 +TIM2-CH3共4路PWM

经测试发现TIM3的CH2,CH4似乎不能同时用DMA???会出现DMA标志已传输完成实际CCR值却没有的情况。于是用TIM-3CH1-3+TIM2-2,3共5路 进行测试


(测试使用buffer value=4进行传输)
4、遇到的其他莫名BUG

按照上述配置,经测试传输较少数据时正常,但是放到实际SK6812灯板上PWM3_3测试不亮,一旦取消PWM2_3DMA的初始化就亮了,这TM???DMA和PWM初始化有冲突???????????
使用示波器发现,TIM3CCR有值但全无PWM输出,一旦注释掉TIM2DMA初始化就有PWM了
但是TIM3寄存器的值全都正确,理论应该有PWM(上图)
而且查看了GPIO寄存器 DMA寄存器 全都正常

实在没有任何逻辑性的头绪,只能使用最后手段 一行行注释代码一遍遍测试
发现注释了TIM2的DMA的初始化 TIM3 的PWM就出来了
我……
虽然很匪夷所思 但是还是联想到可以把所有TIM初始化放在DMA之前试试
我之前的初始化顺序:

修改后的:

于是正常了 我仔细对照查看寄存器和前面不正常时的寄存器值一摸一样,这个BUG已经不是寄存器能解释的了,

至此可以使用5路PWM同时控制2000+颗 SK6812了(本程序已经过实际验证)
虽然已经解决了问题 但是耗费了大量时间调试,有关这些隐晦的初始化顺序关系BUG等等没有在任何手册中看到过,也挺坑的。遇到这种问题只能耗费大量时间进行海量测试才能找到问题
另外还有一点 测试时发现PWM3_2DMA和PWM3_4DMA不能同时使用 否则两者都会异常。这个BUG还没找到是什么原因,可能是芯片设计就是这样,代码难以解决了,先放下了,如果有哪位大神亲自调试过知道原因,望不吝赐教
举报

更多回帖

发帖
×
20
完善资料,
赚取积分