用SPI和DMA驱动WS2812B炫彩LED
在开始进行SPI驱动WS2812B设计之前,先了解一下WS2812B是一个集控制电路与发光电路于一体的智能外控LED光源。其外型与一个050LED灯珠相同,每个元件即为一个像素点。像素点内部包含了智能数字接口数据锁存信号整形放大驱动电路,还包含有高精度的内部振荡器和可编程定电流控制部分,有效保证了像素点光的颜色高度一致。数据协议采用单线归零码的通讯方式,像素点在上电复位以后,DIN端接受从控制器传输过来的数据,首先送过来的24bit数据被第一个像素点提取后,送到像素点内部的数据锁存器,剩余的数据经过内部整形处理电路整形放大后通过DO端口开始转发输出给下一个级联的像素点,每经过一个像素点的传输,信号减少24bit。像素点采用自动整形转发技术,使得该像素点的级联个数不受信号传送的限制,仅受限信号传输速度要求。这个灯现在应用非常广泛,其尺寸如下和引脚。
芯片的供电电压还是有一些要求的,最低要3.7V,为了能更好地驱动它,还得需要用板子上的5V电源。
而数据通信则用3.3V的电平,根据其电器参数表的描述,3.3V的高电平也足够其识别了。
电路设计上,只需要按照如下的串联即可
WS2812B的数据传输采用单线方式,如下为其数据传输时间、时序波形和数据传输方法,可以看到,其数据1和0,分别采用不同的高电平时间来决定。根据时间值,可以估算,数据1和0的总时间可以相同,而高电平时间分别为总时间的2/3和1/3即可,总时间可以设定为1.25uS,相当于是一个约800KHz的方波,只是占空比分别是2/3和1/3来分别待变1和0。但我们采用的是SPI的方式驱动,该方式驱动需要控制每个字节的8位中连续置1的位的个数来实现占空比的调节,根据下面的时间,可以分别采用5bit位和2bie位来表示数值1和数值0,也就是5/8和2/8,相当于781nS和313nS,正好能符合时序所要求的T1H和T0H的时间。
在数据传输的方法中,前面已经提到,首先送过来的24bit数据被第一个像素点提取后,送到像素点内部的数据锁存器,剩余的数据经过内部整形处理电路整形放大后通过DO端口开始转发输出给下一个级联的像素点,每经过一个像素点的传输,信号减少24bit。也就是每个灯,只保留自己收到的第一个24bit数据,剩下的都传给下一个灯。
同时,在传输完一次所有数据之后,需要产生一个RESET信号,该信号时间大于280uS,设计中采用320uS,以满足改时序。
数据在发送时,按照下面的顺序传输,即高位线发送,GRB的顺序发送.
基于上面的内容,可以将WS2812B的电源接到如下J6排针上的的P5LP_VDD引脚进行供电,该引脚为5V电压,从USB接口而来,正好符合要求。
而根据芯片引脚的功能复用定义,可以选择P10.0和P10.1作为MISO和MISO
而选择P10.2作为SCLK引脚
当然,本设计实际只需要MOSI也就够了。
控制只需要接5V的电源以及SPI主机的MOSI引脚。5V就接到板子上的5V电源引脚即可。
打开PSoC Creator,通过芯片系列并使用SPI过滤搜多,发现还是有比较多的demo code的,这里就选择DMA+SPI MAter这个例程。
打开之后更新芯片型号到对应开发板的型号。
研究发现这是一个一颗芯片自发自收的例子。其主要功能就是Master发送命令给Slave,然后控制Slave上的LED灯亮不同的颜色。
甚至自发自收还是在一颗芯片的两个内核上,其中M0内核作为了SPI Slave设备,而M4内核则作为Master设备,说实话,非常妙啊。
但实际上为了驱动灯,只需要作为Master的SPI即可,因此需要将工程适当改造一番。
首先就是去掉Slave
留下Master即可
这时候确认Master的SPI各引脚已经选择正确的引脚了
双击mSPI进行编辑配置
其中最终的的一项就是配置时钟为6.4MHz,保存
SPI Master改成只需要发送
去掉M0的SPI Slave的大部分代码,留下如下main函数即可
接下来根据WS2812B灯带进行设计,首先灯带包含了16颗灯。
因此根据前文介绍的SPI驱动灯带的方法,先定义相关的宏定义和变量,定义包括了灯珠的个数,每颗灯珠的颜色字节数,需要SPI产生生一个颜色的字节数,数据之后更新颜色所需RESET信号的时长以及等效的SPI字节数,WS2812B的三个数据结构体,以及16颗灯珠的数据缓存等,其中数据1使用0x1F,也就是5/8的占空比,数据0使用0x03,也就是2/8的占空比。
实现数据填充函数,实际上就是将颜色转换为SPI每个字节的数据,而最后一个字节则填了0xFF,主要是为了让芯片的MOSI组后输出闭关保持高电平
在主函数中,除了初始化系统及spi接口之外,在主循环中每2秒更新一下16颗灯珠的显示颜色。
SPI接口初始化操作如下,配置使用DMA方式
而下面重点则需要看一下DMA,这颗芯片的DMA非常强大,使用Descriptors进行配置,可以有多个Descriptors,每个最大传输65536个字节。可以实现X和Y的2D的数据传输,入下图。且触发非常灵活,数据量可以极大。
本次使用DMA进行SPI驱动16颗WS2812B,根据前面定义的ws2812b_bit_buffer这个变量数组,需要传输624个数据,因此设计称了10个Descriptors
其中前9个Descripto中每个传输64字节,数据传输单元为Byte,位宽为Byte到Word,源地址需要自增1
第10个则传输624-64*9=48个字节。
每个Descriptor首位相连,且前要给完成之后触发下一个,最终在整个descriptor chain完成之后触发完成中断。
在DMA初始化时,需要手动初始化Descriptor
并指定每个Descriptor的便宜地址
发送函数调用ConfigureTxDma完成上述DMA的配置,并使能DMA通道。且使用变量masterTranStatus进行状态判断
当SPI传输完成时,在中断中清除上述状态
编译下载运行
用逻辑分析仪,可以看到SPI数据输出之后,对应到WS2812B的DI引脚上的频率,约800K,以及数据1和0的占空比情况
在等待上就可以实现每2秒在绿色、红色和蓝色之间切换颜色了。
总结:相对来说,DMA确实非常强大,初次使用,可能感觉还很麻烦,后来发现确实不错,很赞很香。WS2812B也非常好玩,后续还可以调试一些呼吸灯等效果。