搜索
bottom↓
回复: 37

【原创】AVR混编驱动WS2812测试

[复制链接]

出200入2554汤圆

发表于 2015-11-17 12:29:22 | 显示全部楼层 |阅读模式
本帖最后由 t3486784401 于 2015-11-17 12:26 编辑

【背景】

前段时间跟着双十一的节奏,剁手收获了一大批乱七八糟的零件模块,WS2812灯串就是这其中之一。
本来想要买四脚版本的WS2812S,但是店里偏偏只有六脚版的WS2812搞活动,无奈买来几个玩玩。

相对于普通LED,这玩意真心不便宜,一块8灯串的模块就要¥10大洋,总之买来是这样的(背面焊了插座):



网上关于WS2812的驱动,通篇都是 Arduino/ARM/FPGA,既然这样说明 AVR 驱动这玩意还是有望的。
至于 Arduino 怎么做我也没去研究,只是觉着这个事情应该不至于困难到举步维艰的地步。


【C级分析】

看了手册后发现,WS2812的传输码率约为800kbps,直接拿AVR做C语言级别的循环,基本没戏,原因如下:

1. 我板子是 7.3728M 主频的,C转一圈几十个时钟周期松松的(移位、循环判断),直接分频至不到700k;

2. 写驱动就要有通用性,如果都用直接指令写死了(减少移位等运算),那这驱动也就没意义了;

3. AVR没有锁相环诶(PLL),这个在ARM里用烂了的东西,这里不能用了,而且AVR最快也就16M不能瞎搞了。

上述分析,被我第一版纯C的程序证实了:即使数据循环逻辑都对,比特间也有us级的延时,LED失控瞎JB亮。


【汇编分析】

本来就已放弃,打算某日换STM32再战,不想无意中算了下周期,发现很有趣的事情:

1. WS2812规定:逻辑1:H/L=0.85us/0.4us,逻辑0:H/L=0.4us/0.85us,时间比接近 2:1 和 1:2;

2. 对于 7.3728M 主频而言,800kbps 约为其 1/9,即需要每 9T 时间内,完成一个比特的传输;

3. 9T 按照 2:1 和 1:2 分配,居然可以整除!(瞬间RP爆棚了)

上述三条分析的结果是,如果可以实现 H/L=6T/3T、H/L=3T/6T 这样IO代码,就可以正确驱动!
想到这里,我已经开始去翻 AVR 的指令集了(手册上居然有),找到这么几个有希望的指令:

a) sbi  P, b        // 2T, P|= (1<<b)
b) cbi  P, b        // 2T, P&= ~(1<<b)
c) out  P, Rr        // 1T, P = Rr
d) ld   Rd, X+        // 2T, Rd= *(X++)

由于需要间接寻址(内存中颜色数据影响到比特内容),所以 ld 这条指令基本必不可少了(2T);
访问端口的话,sbi/cbi虽然很好用,但一则需要 2T 太浪费,二则需要控制分支,最终选择用out,
置位、复位操作的数值用两个寄存器事先准备好,直接out就可以在 1T 时间内完成输出;

为了给循环控制挤出时间,将9T拆分为3*3T,前段确定为H输出,后段确定为L输出,中段为数据。
每段的最终输出使用out指令,因而每段当中还有2T空闲,可以用作加载、循环控制


【混编实现】

有了上述分析,就可以着手开始工作了。整个程序框架由C生成,在关键的 WS2812_Write 当中,
通过内嵌汇编的方式,确保 out 指令间隔严格为3T,实现WS2812驱动逻辑。

这个源码我在M64/M8上都跑过,除了头文件和MCU设置,其他直接移植就可用,
说明内嵌的汇编仅涉及AVR内核,在MEGA(甚至是TINY)系列当中还是可以复用的。

实测加载8个灯约5ms,这个性能将来刷动画是妥妥有希望的。

直接上源码(ICCAVR v7.22):

附带个手册(六脚WS2812):


【运行效果】

我只写了几个简单的颜色进去,稍后再改动画吧:






【后记】

不知不觉中感觉AVR也就那样了,毕竟有些年头了再加上ATMEL的态度,难怪新品都投奔ARM去了。
不过在稳定的平台上,做出些稳定的东西,终究是有人要的,Arduino就是很好的例子。



-----------------------------------------------------------------------------
不写了,[吃饭去鸟].....(((((ヾ( o=^•ェ•)o ┏━┓

本帖子中包含更多资源

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

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2015-11-18 08:58:49 | 显示全部楼层
技术贴,值得学习!

出130入20汤圆

发表于 2015-11-18 09:07:36 | 显示全部楼层
不错,楼主时间好多啊。AVR用起来还是不错的,虽然已经不敌M0

出0入4汤圆

发表于 2015-11-18 09:17:12 来自手机 | 显示全部楼层
用硬件SPI驱动WS2812这类的芯片还是很开心的

出200入2554汤圆

 楼主| 发表于 2015-11-18 10:36:46 | 显示全部楼层
shuiluo2 发表于 2015-11-18 09:07
不错,楼主时间好多啊。AVR用起来还是不错的,虽然已经不敌M0

其实是没有细去思考 5-3.3 之间的转换,才拿AVR来偷懒的:)

出200入2554汤圆

 楼主| 发表于 2015-11-18 10:39:00 | 显示全部楼层
zqf441775525 发表于 2015-11-18 09:17
用硬件SPI驱动WS2812这类的芯片还是很开心的

也是个好办法啊,不过AVR的SPI不带DMA也不带FIFO,数据发送连不上是个头痛的事情

这么一想还是投奔ARM吧

出0入4汤圆

发表于 2015-11-18 10:41:02 | 显示全部楼层
t3486784401 发表于 2015-11-18 10:39
也是个好办法啊,不过AVR的SPI不带DMA也不带FIFO,数据发送连不上是个头痛的事情

这么一想还是投奔ARM吧 ...

嗯,很对,得要带DMA的SPI,我就是这么驱动的,而且它的1和0的高电平时间和低电平时间我实际测试过没必要那么精准,误差30-40%都是可以的。

出200入2554汤圆

 楼主| 发表于 2015-11-18 11:15:08 | 显示全部楼层
zqf441775525 发表于 2015-11-18 10:41
嗯,很对,得要带DMA的SPI,我就是这么驱动的,而且它的1和0的高电平时间和低电平时间我实际测试过没必要 ...

不过感觉还是略有浪费,SPI 开了后好些引脚就占用了(SCK/MISO)....

用UART还好,不过UART静态是高电平状态,又需要反相器了....

出0入4汤圆

发表于 2015-11-18 11:26:51 | 显示全部楼层
t3486784401 发表于 2015-11-18 11:15
不过感觉还是略有浪费,SPI 开了后好些引脚就占用了(SCK/MISO)....

用UART还好,不过UART静态是高电平 ...

STM32的SPI好像有单输出模式,只占用两个口,一个SCK,一个MOSI。

出200入2554汤圆

 楼主| 发表于 2015-11-20 02:14:21 | 显示全部楼层
zqf441775525 发表于 2015-11-18 11:26
STM32的SPI好像有单输出模式,只占用两个口,一个SCK,一个MOSI。

这样很好嘛

不过既然用DMA了,不妨直接 MEM 到 IO 试试看,就是需要额外一个定时器咯

出20入0汤圆

发表于 2015-11-20 02:19:08 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2015-11-30 12:04:29 | 显示全部楼层
好东西,我来上传个WS2812  的PDF吧

本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2015-12-4 12:56:55 来自手机 | 显示全部楼层
GCC内联汇编吗?前段时间刚用,感觉不熟悉。

出0入0汤圆

发表于 2015-12-5 13:46:36 来自手机 | 显示全部楼层
dma加pwm的路过

出200入2554汤圆

 楼主| 发表于 2015-12-5 23:08:39 | 显示全部楼层
wrmike 发表于 2015-12-4 12:56
GCC内联汇编吗?前段时间刚用,感觉不熟悉。

ICC内联汇编,需要效率就只能这么做了,换控制器那是另一条路

出0入0汤圆

发表于 2015-12-6 00:30:51 | 显示全部楼层
用LGT驱动过TM1812,2812还没研究过。

出0入0汤圆

发表于 2015-12-6 18:26:59 来自手机 | 显示全部楼层
彩灯?多少位色深

出200入2554汤圆

 楼主| 发表于 2015-12-7 12:03:15 | 显示全部楼层
HYLG 发表于 2015-12-6 00:30
用LGT驱动过TM1812,2812还没研究过。

2812最难的地方在于高速,比特流一旦开始传,800kbps 就不能断

出200入2554汤圆

 楼主| 发表于 2015-12-7 12:04:25 | 显示全部楼层
huangqi412 发表于 2015-12-6 18:26
彩灯?多少位色深

24bit真彩的,实际 LED 在比较亮的时候基本就看不太清楚了

出0入0汤圆

发表于 2015-12-28 00:10:21 | 显示全部楼层
Arduino,attiny85,8个引脚,也能驱动这个2812。 读了文章后,估计也是汇编编写~~

出200入2554汤圆

 楼主| 发表于 2015-12-28 01:08:13 | 显示全部楼层
zbjzxc 发表于 2015-12-28 00:10
Arduino,attiny85,8个引脚,也能驱动这个2812。 读了文章后,估计也是汇编编写~~ ...

是的,这个对内存消耗不大(如果灯带不是很长的话),关键在于 AVR 内核级的 IO 模拟,需要很快的速度才能实现 NRZ 编码

出0入4汤圆

发表于 2015-12-28 05:49:13 | 显示全部楼层
好文!

AVR 可以跑到 20MHz.

前段时间也用 WS2812B 做了一个项目(图案跑的是 Conway's Game of Life):


驱动用的是 http://fastled.io/
一篇驱动的相关文章
Light_WS2812 library V2.0 – Part I: Understanding the WS2812
https://cpldcpu.wordpress.com/20 ... tanding-the-ws2812/

本帖子中包含更多资源

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

x

出0入4汤圆

发表于 2015-12-28 09:32:40 | 显示全部楼层
3*8也就是11个端口,即使每个灯条搞一个stm32f030f4也差不多10元,不知道我算的对不对,然后uart,iic,spi想定义什么方法用什么方法通信。16k可以写很多样式出来吧。楼主考虑一下啊,我很早想搞着玩,一直没动手,用空一起来整。

出200入2554汤圆

 楼主| 发表于 2015-12-28 10:22:20 | 显示全部楼层
buck 发表于 2015-12-28 04:27
这个要gamma曲线校正的,亮度和电压是指数关系

2812 据手册讲是自带 GAMMA 校正的,实际用起来仅仅一致性可以,但裸眼亮度需要拿纸罩住才有比较好的线性

出200入2554汤圆

 楼主| 发表于 2015-12-28 10:24:06 | 显示全部楼层
atommann 发表于 2015-12-28 05:49
好文!

AVR 可以跑到 20MHz.

感觉上 WS2811 这个芯片可以更给力,每片带 3 个通道(要是更多也不错)

这样驱动白光的话,灰度屏有希望啊

出200入2554汤圆

 楼主| 发表于 2015-12-28 10:34:23 | 显示全部楼层
gmyu 发表于 2015-12-28 09:32
3*8也就是11个端口,即使每个灯条搞一个stm32f030f4也差不多10元,不知道我算的对不对,然后uart,iic,spi ...

以前用 M64/128 做过类似的东西,所有 RGB 公用一个三通道 PWM 发生器(OC1A/B/C),每个 LED 单独一个 IO 进行选通扫描。

最后一片 M64 带了 30 只全彩 LED,分两组进行扫描(1/15占空比),通过 GAMMA 校正后每个颜色大约有 8 位灰度。

剩下就是怎么写效果了.....

出0入4汤圆

发表于 2015-12-28 10:59:32 | 显示全部楼层
t3486784401 发表于 2015-12-28 10:34
以前用 M64/128 做过类似的东西,所有 RGB 公用一个三通道 PWM 发生器(OC1A/B/C),每个 LED 单独一个 I ...

效果如何?

出0入4汤圆

发表于 2015-12-28 11:26:18 | 显示全部楼层
t3486784401 发表于 2015-12-28 10:34
以前用 M64/128 做过类似的东西,所有 RGB 公用一个三通道 PWM 发生器(OC1A/B/C),每个 LED 单独一个 I ...

以前PIC的代码,软件PWM,感觉效果不好就没玩了。

本帖子中包含更多资源

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

x

出200入2554汤圆

 楼主| 发表于 2015-12-28 12:11:23 | 显示全部楼层

基本上就是仿老外那个 Aurora 项目的效果,不过 LED 没买到雾面的不爽。

直接板子的视频没录,这里有个套上了柚子皮(我女票太有才)的效果:

http://player.youku.com/player.php/sid/XMTM2MzMzMzc1Mg==/v.swf

出0入4汤圆

发表于 2015-12-28 12:19:31 | 显示全部楼层
t3486784401 发表于 2015-12-28 12:11
基本上就是仿老外那个 Aurora 项目的效果,不过 LED 没买到雾面的不爽。

直接板子的视频没录,这里有个 ...

有才,单纯的呼吸变色,你几十个LED搞出啥花样了?

出200入2554汤圆

 楼主| 发表于 2015-12-29 01:04:45 | 显示全部楼层
gmyu 发表于 2015-12-28 12:19
有才,单纯的呼吸变色,你几十个LED搞出啥花样了?

这是焊接效果图,以及刚录制的视频:



http://player.youku.com/player.php/sid/XMTQyODM2ODc1Mg==/v.swf

本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2015-12-31 18:04:30 | 显示全部楼层
我直接拿PIC的PIC12F1572做12个灯的WS2812B,不会用CLC CWG NCO,所以就直接循环发送,很笨,不过还是做出来了~有12个模式~回头发一下视频哈哈哈~

出200入2554汤圆

 楼主| 发表于 2016-1-3 23:58:49 | 显示全部楼层
yoursnemo 发表于 2015-12-31 18:04
我直接拿PIC的PIC12F1572做12个灯的WS2812B,不会用CLC CWG NCO,所以就直接循环发送,很笨,不过还是做出来了~ ...

非常期待该作品!!

出0入0汤圆

发表于 2016-1-14 15:01:45 | 显示全部楼层
zqf441775525 发表于 2015-11-18 09:17
用硬件SPI驱动WS2812这类的芯片还是很开心的

可以这样玩!

出0入0汤圆

发表于 2016-1-14 15:06:19 | 显示全部楼层
学习中,谢谢楼主分享!

出0入0汤圆

发表于 2017-7-27 14:38:44 | 显示全部楼层
本帖最后由 辣条 于 2017-7-27 15:53 编辑

楼主,用您提供的程序测试确实好用,另外我用的晶振是14.7456Mhz的,在汇编中加入几个延时就能用。但我用的是mega168,1kRAM,只能驱动40多个灯,不然内存不够用啦?(由于您代码中把一位变为一个字节表示,那么驱动一个灯就需要一个24字节的数组)能否可可以把汇编部分改为按位输出的呢?想用您的这个底层驱动更多灯数,有好的办法吗!?

出200入2554汤圆

 楼主| 发表于 2017-7-28 17:59:05 | 显示全部楼层
辣条 发表于 2017-7-27 14:38
楼主,用您提供的程序测试确实好用,另外我用的晶振是14.7456Mhz的,在汇编中加入几个延时就能用。但我用的 ...

14.7456MHz 下,每个循环多出了 9T 的时间,好好安排指令的话,应该可以实现驱动。目前有这么个思路:

1. 建议循环还是一圈走一个字节,因为 LD 指令(对应 *(ptr++) 之类的操作)比较耗时。这样的话CPU负载比较稳定;

2. 使用 BST/BLD 指令,将字节的各个位逐一搬运到目标端口比特;

3. 这个需要排指令,建议用 EXCEL 好好规划一下指令,按时间要求(8*18T),逐一编排;

我用 7.3728MHz 的 m328p 曾经实现过这个需求,每 3B-RAM 对应一个灯。不过不巧手头找不着这个版本了。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-4-26 23:43

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

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