stm32和ws2812B相对较好的方案。SPI和UART

2019-12-09 19:12发布

最近看不少人玩ws2812b。我搜了一下找到个比较好的。
这个程序是spi+dma的,我修改了下在F030F4上面跑着挺好。大概的意思是E表示1。8表示0。一个字节处理两位。

我想了一下UART+DMA,没有时间做。如果用UART,设置到2.4M,每个位400nS(spec.: 250-550),  反转一下,每三位处理一个bit,高高低表示1(800+400),低低高表示0(800+400)。 这样start+76位,543,210,总共一个字节处理3个位,停止位因为反转了就是低电平,间隔时间不足50uS,应该没影响。
如此,每24/3=8个字节处理一个灯,比SPI的12个字节更少。个位有什么看法。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
36条回答
gmyu
1楼-- · 2019-12-10 12:14
 精彩回答 2  元偷偷看……
20061002838
2楼-- · 2019-12-10 14:02
发送一个LED的数据所需要的时间是 1.25*24 = 32us
而CPU生成数据所需的时间远远小于32us
那么就有了使用双缓冲,乒乓操作的条件
两个缓冲区,每个缓冲区处理25个LED,总共占用RAM:SPI 25*12*2 = 600bytes; USART 25*24*2 = 1200bytes,而且扩展到更长的灯带时不需要增加缓冲区长度
DMA传输完成中断产生后,最后两个个字节(SPI是半字)数据一个在移位寄存器中发送,另一个在TDR寄存器中等待发送,中断函数里面等待TXE标志位置位,重新配置DMA
gmyu
3楼-- · 2019-12-10 19:59
20061002838 发表于 2018-8-16 17:10
发送一个LED的数据所需要的时间是 1.25*24 = 32us
而CPU生成数据所需的时间远远小于32us
那么就有了使用双 ...

不用缓冲区,直接写DMA的buff会出现什么情况。基本上写buff很短时间,可以在刷新ws2812的时候做。或者就算正在发送spi,更新dma数据区会怎么样。

你已经用UART实现了,对么?貌似是一个bit对一个字节。
20061002838
4楼-- · 2019-12-11 01:17
gmyu 发表于 2018-8-16 17:24
不用缓冲区,直接写DMA的buff会出现什么情况。基本上写buff很短时间,可以在刷新ws2812的时候做。或者就 ...

不用双缓冲,直接写DMA的buf,不就把正在发送的数据给破坏了吗

没玩过WS2812,UART是前两天给坛友设计的一个方案,很容易可以翻到,用USART,同步模式,外部用D触发器,通过时钟信号锁存数据
没验证过
gmyu
5楼-- · 2019-12-11 01:27
20061002838 发表于 2018-8-16 17:39
不用双缓冲,直接写DMA的buf,不就把正在发送的数据给破坏了吗

没玩过WS2812,UART是前两天给坛友设计的 ...

我上面说了,TX反转电平,加开始位可以看作9个bit,这样可以处理3个LED位,不用外接器件,不过没有试过。

btw,上面的程序我运行有点问题,颜 {MOD}编码通常是rgb,但是ws2812用的是gbr,他虽然做了处理,但是颜 {MOD}不对。
改了一下这个函数,把循环也去掉,运行可能快点。
void Sw28_SetPixelsColor(SW28_HandleTypeDef *swObj, uint8_t pix, uint32_t color)
{
    uint8_t g; //r,g,b;
    uint8_t        *pb = swObj->BuffPoint + pix*12;

                        g= (uint8_t)(color>>8);
                        *pb++ = LED2B[g & 0x03]; g >>= 2;
                        *pb++ = LED2B[g & 0x03]; g >>= 2;
                        *pb++ = LED2B[g & 0x03]; g >>= 2;
                        *pb = LED2B[g & 0x03];
                        g= (uint8_t)(color>>16);
                        *pb++ = LED2B[g & 0x03]; g >>= 2;
                        *pb++ = LED2B[g & 0x03]; g >>= 2;
                        *pb++ = LED2B[g & 0x03]; g >>= 2;
                        *pb = LED2B[g & 0x03];
                        g= (uint8_t)(color);
                        *pb++ = LED2B[g & 0x03]; g >>= 2;
                        *pb++ = LED2B[g & 0x03]; g >>= 2;
                        *pb++ = LED2B[g & 0x03]; g >>= 2;
                        *pb = LED2B[g & 0x03];
}
20061002838
6楼-- · 2019-12-11 02:49
 精彩回答 2  元偷偷看……

一周热门 更多>