搜索
bottom↓
回复: 40

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

  [复制链接]

出0入4汤圆

发表于 2018-8-15 14:51:49 | 显示全部楼层 |阅读模式
最近看不少人玩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个字节更少。个位有什么看法。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2018-8-15 15:30:56 | 显示全部楼层
直接用IO,写得我要吐了。

出0入0汤圆

发表于 2018-8-15 15:38:26 | 显示全部楼层
uart还是比较复杂的吧,有校验位停止位什么的,还是PWM+DMA最直接明了。

出0入0汤圆

发表于 2018-8-15 15:40:59 | 显示全部楼层
SPI的方式不错,速度慢的单片机都可以做

出0入0汤圆

发表于 2018-8-15 15:48:48 | 显示全部楼层
谢谢楼主分享。

出0入4汤圆

 楼主| 发表于 2018-8-15 16:00:27 | 显示全部楼层
Eiman 发表于 2018-8-15 15:38
uart还是比较复杂的吧,有校验位停止位什么的,还是PWM+DMA最直接明了。

校验位可以没有的,电压反转后,开始位必须是高,和2812协议相同,停止位作为间隔可以忽略。

想问一下pwm占用多少RAM和CPU资源。是不是整个DMA发送完成才需要CPU参与一次,论坛那位貌似现在没搞定,不知卡在哪里。

出0入0汤圆

发表于 2018-8-15 16:18:47 | 显示全部楼层
gmyu 发表于 2018-8-15 16:00
校验位可以没有的,电压反转后,开始位必须是高,和2812协议相同,停止位作为间隔可以忽略。

想问一下pw ...

我的是PWM+DMA点亮60个WS2812B没问题啊。  
占用空间如下:
8 808 bytes of readonly  code memory
    352 bytes of readonly  data memory
  5 554 bytes of readwrite data memory

出0入4汤圆

 楼主| 发表于 2018-8-16 11:35:31 | 显示全部楼层
Eiman 发表于 2018-8-15 16:18
我的是PWM+DMA点亮60个WS2812B没问题啊。  
占用空间如下:
8 808 bytes of readonly  code memory

我用F030F4,只有4K RAM, 你这个远远超出,假定100个灯,100*2*24就4.8k了,而用SPI就只需要100*12=1.2kbyte。 这个差距还是比较大的,毕竟还要做各种效果,加上buffer就更不敢用pwm了。

出0入24汤圆

发表于 2018-8-16 17:10:01 | 显示全部楼层
发送一个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

出0入4汤圆

 楼主| 发表于 2018-8-16 17:24:53 | 显示全部楼层
20061002838 发表于 2018-8-16 17:10
发送一个LED的数据所需要的时间是 1.25*24 = 32us
而CPU生成数据所需的时间远远小于32us
那么就有了使用双 ...

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

你已经用UART实现了,对么?貌似是一个bit对一个字节。

出0入24汤圆

发表于 2018-8-16 17:39:54 | 显示全部楼层
gmyu 发表于 2018-8-16 17:24
不用缓冲区,直接写DMA的buff会出现什么情况。基本上写buff很短时间,可以在刷新ws2812的时候做。或者就 ...

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

没玩过WS2812,UART是前两天给坛友设计的一个方案,很容易可以翻到,用USART,同步模式,外部用D触发器,通过时钟信号锁存数据
没验证过

出0入4汤圆

 楼主| 发表于 2018-8-16 18:13:05 | 显示全部楼层
20061002838 发表于 2018-8-16 17:39
不用双缓冲,直接写DMA的buf,不就把正在发送的数据给破坏了吗

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

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

btw,上面的程序我运行有点问题,颜色编码通常是rgb,但是ws2812用的是gbr,他虽然做了处理,但是颜色不对。
改了一下这个函数,把循环也去掉,运行可能快点。
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];
}

出0入24汤圆

发表于 2018-8-16 18:20:45 | 显示全部楼层
本帖最后由 20061002838 于 2018-8-16 18:25 编辑
gmyu 发表于 2018-8-16 18:13
我上面说了,TX反转电平,加开始位可以看作9个bit,这样可以处理3个LED位,不用外接器件,不过没有试过。 ...


查表最快,没有之一

看错了,你这个就是查表

出0入4汤圆

 楼主| 发表于 2018-8-16 18:41:12 | 显示全部楼层
本帖最后由 gmyu 于 2018-8-16 18:43 编辑
20061002838 发表于 2018-8-16 18:20
查表最快,没有之一

看错了,你这个就是查表


请问,查表返回的一个32bit常量放到8位数组buffer里面,那种方法最快?谢谢!

出0入24汤圆

发表于 2018-8-16 18:47:42 | 显示全部楼层
gmyu 发表于 2018-8-16 18:41
请问,查表返回的一个32bit常量放到8位数组buffer里面,那种方法最快?谢谢!  ...

指针,强制类型转换
  1. void WS2812b_Display(void)
  2. {
  3.     register  unsigned long i;
  4.     register  unsigned char temp = 0;

  5.     register  unsigned short const *pSrc;
  6.     register  unsigned short  *pDrc;

  7.     register unsigned short b1, b2, b3;

  8.     pDrc = (unsigned short *)spi_SendBuf;

  9.     for (i = 0; i < 48; i++)//轮询像素缓存区
  10.     {
  11.         temp = ws2812b_PixBuf[i] >> 4;

  12.         pSrc = (unsigned short const *)LUTbl[temp];

  13.         b1 = *pSrc++;
  14.         b2 = *pSrc++;
  15.         b3 = *pSrc++;

  16.         *pDrc++ = b1;
  17.         *pDrc++ = b2;
  18.         *pDrc++ = b3;

  19.         temp = ws2812b_PixBuf[i] & 0x0F;

  20.         pSrc = (unsigned short const *)LUTbl[temp];

  21.         b1 = *pSrc++;
  22.         b2 = *pSrc++;
  23.         b3 = *pSrc++;

  24.         *pDrc++ = b1;
  25.         *pDrc++ = b2;
  26.         *pDrc++ = b3;

  27.     }
  28. #if 0     
  29.     DMA_Cmd(DMA1_Channel3, DISABLE);
  30.     DMA_ClearFlag(DMA1_FLAG_TC3);
  31.     DMA1_Channel3->CNDTR = SENDLENGTH;
  32.     DMA_Cmd(DMA1_Channel3, ENABLE);
  33. #endif   
  34. }
复制代码

出0入4汤圆

 楼主| 发表于 2018-8-16 19:20:06 | 显示全部楼层
20061002838 发表于 2018-8-16 18:47
指针,强制类型转换





对C++不熟悉,高手可以移植这个到stm32就好了,我在arduino下运行很炫,53种模式,可扩展性很强,如果用systick处理里面的step,延时也不消耗cpu资源了。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2018-8-17 09:56:31 | 显示全部楼层
gmyu 发表于 2018-8-16 11:35
我用F030F4,只有4K RAM, 你这个远远超出,假定100个灯,100*2*24就4.8k了,而用SPI就只需要100*12=1.2k ...

100灯也就100*24就可以了,我用了5K多主要是我没省着用,还用了HSB颜色空间转换保存每一个灯的参数。

出0入4汤圆

 楼主| 发表于 2018-8-17 10:36:25 | 显示全部楼层
Eiman 发表于 2018-8-17 09:56
100灯也就100*24就可以了,我用了5K多主要是我没省着用,还用了HSB颜色空间转换保存每一个灯的参数。 ...

pwm dma data你用的是16位还是8位?

出0入0汤圆

发表于 2018-8-17 11:26:48 | 显示全部楼层
gmyu 发表于 2018-8-17 10:36
pwm dma data你用的是16位还是8位?

是哦,一时没想起来。

出0入8汤圆

发表于 2018-8-22 08:40:49 来自手机 | 显示全部楼层
stm32的io需要电平转换吗?ws2812是5V的,要3.5V才算高。我现在是把ws2812的vcc通过5V串1N4007后将为4.3V。你们是怎么做啊?

出0入4汤圆

 楼主| 发表于 2018-8-22 08:51:46 | 显示全部楼层
3.5才算高? 我直接连的。正常。

出0入8汤圆

发表于 2018-8-23 01:08:56 来自手机 | 显示全部楼层
资料上写的是0.7倍的VCC才是高电平的啊吧?

出0入0汤圆

发表于 2018-9-10 21:28:45 | 显示全部楼层
学习中 谢谢

出0入0汤圆

发表于 2018-10-30 03:53:19 来自手机 | 显示全部楼层
Eiman 发表于 2018-8-15 15:38
uart还是比较复杂的吧,有校验位停止位什么的,还是PWM+DMA最直接明了。

我用stc的PWM好像有点搞不定,好像30M情况下,37个周器,进中断再处理就超过了

出0入0汤圆

发表于 2018-10-30 09:27:10 | 显示全部楼层
weatt123456789 发表于 2018-10-30 03:53
我用stc的PWM好像有点搞不定,好像30M情况下,37个周器,进中断再处理就超过了 ...

所以用DMA处理就简单些

出0入0汤圆

发表于 2018-11-3 18:45:39 | 显示全部楼层
为什么不用PWM呢

出0入0汤圆

发表于 2018-11-3 19:02:39 来自手机 | 显示全部楼层
楼主最后结果呢

出0入4汤圆

 楼主| 发表于 2018-11-3 19:15:51 | 显示全部楼层
UART没用,因为换207资源大大的有了。

出0入4汤圆

发表于 2019-1-11 11:58:31 | 显示全部楼层
gmyu 发表于 2018-11-3 19:15
UART没用,因为换207资源大大的有了。

莫名碰到WS2812该亮得时候不亮,不亮得时候瞎亮

出0入4汤圆

发表于 2019-1-11 12:00:01 | 显示全部楼层
gmyu 发表于 2018-11-3 19:15
UART没用,因为换207资源大大的有了。


不知道是不是0码和1码配置得问题。用的是SPI接口。

出0入4汤圆

发表于 2019-1-11 12:22:36 | 显示全部楼层
有没有人搞过w2812做成点阵显示酷炫特效的?

不知道能否实现,就是类似跳舞机那种

出0入0汤圆

发表于 2019-1-25 10:09:23 | 显示全部楼层
了解一下!!

出0入0汤圆

发表于 2019-2-16 13:48:44 | 显示全部楼层
20061002838 发表于 2018-8-16 18:47
指针,强制类型转换

STM32F103  可以实现控制1024个灯珠?

出0入0汤圆

发表于 2019-4-24 23:54:10 | 显示全部楼层
你的SPI接哪呢?简易的电路图有吗?或者说明一下接法。

出0入4汤圆

 楼主| 发表于 2019-4-26 09:57:45 | 显示全部楼层
smilelinux 发表于 2019-4-24 23:54
你的SPI接哪呢?简易的电路图有吗?或者说明一下接法。

sdo到2812的data脚

出0入0汤圆

发表于 2019-4-26 10:03:48 | 显示全部楼层
mark一下,空了画个电路板试试

出0入0汤圆

发表于 2019-11-18 23:08:57 来自手机 | 显示全部楼层
楼主,没看到你程序里面WS2812B的RESET信号怎么产生

出0入4汤圆

 楼主| 发表于 2022-10-14 16:06:57 | 显示全部楼层
花了一天在arm926上用UART dma实现了。每个UART发3个bits。24bits需要8个串口bytes。
下面是查表转颜色到UART数据。
UINT8 RGB2UART[] = {0xDB,0x9B,0xD3,0x93,0xDA,0x9A,0xD2,0x92};

void Send_24b_1LED(UINT8* Led_Arr, UINT32 u32color)
{UINT8 u8bit3,u8color;
        for(UINT8 i = 0; i<8; i++){
                u8color = (UINT8)(u32color >> (21-3*i));  //先高后低G-R-B
                u8bit3 = u8color & 0x7 ;
                * (Led_Arr+i) = RGB2UART[u8bit3];

  }
}

这个内存有64M,所以再不用考虑内存了,开两个buff采用乒乓的形式去刷新。

出0入4汤圆

 楼主| 发表于 2022-10-14 16:14:06 | 显示全部楼层
改了一下,把乘法那个去掉了。
void Send_24b_1LED(UINT8* Led_Arr, UINT32 u32color)
{UINT8 u8bit3,u8shift;
        u8shift = 21;
        for(UINT8 i = 0; i<8; i++){
                u8bit3 = ((UINT8)(u32color >> u8shift)) & 0x7;  //
                u8shift -= 3;
                * (Led_Arr+i) = RGB2UART[u8bit3];

  }
}

出0入4汤圆

 楼主| 发表于 2022-10-15 11:58:36 | 显示全部楼层
https://github.com/lamik/WS2812B_STM32_HAL
https://blog.csdn.net/Tkwer/article/details/104740550
别人的移植

出0入53汤圆

发表于 2022-10-15 16:15:14 | 显示全部楼层
gmyu 发表于 2022-10-15 11:58
https://github.com/lamik/WS2812B_STM32_HAL
https://blog.csdn.net/Tkwer/article/details/104740550
别 ...
(引用自40楼)

看网上视频有用8s003做的很炫的,不知道咋搞出来的,我 感觉我的45MHz频率都吃力
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-19 10:00

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表