单片机软件设计1-使用SPI+DMA驱动WS2812B型LED
<div class='showpostmsg'> 本帖最后由 dql2016 于 2017-4-15 19:57 编辑最近太忙了,实在事不好意思,今天抽空分享一下如何使用STM32CubeMX快速配置SensorTile的SPI接口,用来驱动WS2812B型全彩LED。参考了网友zoomdy的帖子http://www.stmcu.org/module/forum/thread-610279-1-1.html,在此对zoomdy无私的分享精神表示感谢。
下面事它的时序图,十分特殊,相当于是用不同脉宽的PWM信号来表示它的一个位,虽然灯珠电气参数要求的电压比SenSorTile的3.3V要大一点点,但实测还是能完全驱动的,只需三根线(电源需用5V,地线,信号线)即可驱动,理论上可“无限”级联,实际上级联过多时,信号会产生畸变,且功率还是非常大的,每颗灯珠最多60mA电流,因此要选用合适的电源才行。
使用SensorTile的SPI来模拟它的时序,SPI配置为8位数据模式,假设其传输速率为b Mbit/s,即b/8 MB/s=b/8 Byte/us,传输一个字节需要8/b us,用1字节的SPI数据来表示WS2812B的一位数据。假设SPI发送的1字节数据中连续“1”的个数为n,按照时序要求,对于1码:那么n需要满足如下关系:n/8 * 8/b~(0.85us+/-150ns);对于0码:那么n需要满足如下关系:n/8 * 8/b~(0.4us+/-150ns);考虑到信号的上升沿等因素,SPI发送的1字节数据其最高位均取“0”。这里我配置SPI速率为1Mbit/s时,SPI发送的1字节数据0x70(0111 0000)表示WS2812B的0码,SPI数据0x7C(0111 1100)表示WS2812B的1码。一颗WS2812B需要24位数据(按照绿-红-蓝顺序,高位在前)。
STM32CubeMX对SPI的关键配置如下:
如下图Adafruit_NeoPixel.c文件,先编写一个发送8个位的函数,使用了DMA:
然后是发送24个位的:
我在底层驱动的基础上移植了Arduino平台的Adafruit_NeoPixel库函数,提供丰富的应用函数,如彩虹、呼吸等效果。
这是Adafruit_NeoPixel.h文件内容:
使用时只需配置好SPI后把下面2个文件添加进工程即可:
在main函数调用初始化后,即可愉快的玩耍了:
效果图见此帖:https://bbs.eeworld.com.cn/thread-525615-1-1.html
附上工程文件:
</div><script> var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;" style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
if(parseInt(discuz_uid)==0){
(function($){
var postHeight = getTextHeight(400);
$(".showpostmsg").html($(".showpostmsg").html());
$(".showpostmsg").after(loginstr);
$(".showpostmsg").css({height:postHeight,overflow:"hidden"});
})(jQuery);
} </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script> 谢谢分享!!! 好想法,学习一下
谢谢分享!!!正想找这个。 谢谢楼主分享 谢谢楼主分享 借鉴下 谢谢啦, 移植看下效果 谢谢分享 来学习下这个 学习学习,谢谢分享 SPI传输每传输8位中间有间歇哈?这个弄? 感谢分享 哇感谢大佬!一只萌新路过 昨天看了大佬的教程,今天把东西弄出来了,过来补充一些。首先一开始不太理解大佬说的0码跟1码,后来抓了波形才懂,其实1码最左边的0,作为是上一个数据的补充,0码同理。大佬这一招很妙!另外大佬spi的速率应该是不对的吧?1Mbit/s的话8位数据的时间就是8us远超一个ws2812数据码的周期。所以一开始移植的时候(一开始为了节约时间没有仔细研究大佬说的话)死活调不通,后来25us发现spi速率配错了。emmm我自己配的速率8位数据1.25us直接跟他对应起来,每一位就是的时间1.25/8,速率就是8/1.25=6.4M。为了这6.4M我还专门去调了stm32f4的总线时钟频率,结果当然是降频了,感觉有点得不偿失。总之还是为了提醒大家学习要多专研啊!也给大家提提醒,顺便谢谢大佬的指教了! 风狼 发表于 2019-1-10 16:55
昨天看了大佬的教程,今天把东西弄出来了,过来补充一些。首先一开始不太理解大佬说的0码跟1码,后来抓了波 ...
楼主的这种方式有些浪费内存资源
使用SPI最节省内存的方法是用3bit来实现ws2812的一位
SPI时钟在2.5Mbps左右时可以用100=0,110=1
这样ws2812b的24位数据可以使用9个字节实现
具体可以看一下我的贴子 littleshrimp 发表于 2019-1-10 19:37
楼主的这种方式有些浪费内存资源
使用SPI最节省内存的方法是用3bit来实现ws2812的一位
SPI时钟在2.5Mbp ...
嗯嗯确实,谢谢指教。 好东西啊,经典 这个历程比较巧妙的用多位SPI的数据来达到高电平长短的标识,来实现WS2812的时序要求,最有意思的是能够移植arduino的库,我用过那个库确实很炫,厉害厉害,哈哈哈哈:):):)
页:
[1]
2