本帖最后由 YvonneOH- 于 2019-11-25 15:14 编辑
WS2812B是一个集控制电路与发光电路于一体的智能外控LED光源。其外型与一个5050LED灯珠相同,每个元件即为一个像素点。像素点内部包含了智能数字接口数据锁存信号整形放大驱动电路,还包含有高精度的内部振荡器和12V高压可编程定电流控制部分,有效保证了像素点光的颜色高度一致。 通讯协议说明: 数据协议采用单线归零码的通讯方式,像素点在上电复位以后,DIN端接受从控制器传输过来的数据,首先送过来的24bit数据被第一个像素点提取后,送到像素点内部的数据锁存器,剩余的数据经过内部整形处理电路整形放大后通过DO端口开始转发输出给下一个级联的像素点,每经过一个像素点的传输,信号减少24bit。也就是说,第一颗灯珠将读取从MCU传输过来的所有数据,取其中24位作为自身数据,并将其余数据整形后向后传递,以此类推,直到数据传送完成。之后,MCU发送一个>=50us的低电平,ws281x芯片复位,重新开始第二次数据传输。
这种通信方式大大节省了所需MCU的引脚,但是,缺点也很明显。数据的0位和1位通过高电平和低电平的时间来控制,精确度在纳秒级别(0位和1位各占1.25us),对低速MCU极其不友好。
参看时序波形图可以发现,0位和1位都是通过一个1.25us+-300ns(也有150ns或者600ns的,300ns比较常见)左右的信号来实现 0Bit:三分之一的高电平加上三分之二的低电平 1Bit: 三分之二的高电平加上三分之一的低电平 Reset:超过50us的低电平 每一芯片单元的24Bit数据按照G8位R8位B8位来编码,想要实现相应的颜色可以参考RGB色表。
引脚: 芯片有四个引脚Vcc Gnd D0 D1
驱动方法: 目前大概有三种驱动方法: l GPIO配合机器空周期直接驱动。 l PWM+DMA驱动 l SPI+DMA驱动 第三种没做过实验,这里就不讲了。 1.GPIO配合机器空周期直接驱动稳定性比较差,需要配合示波器测出准确的延时。而且,数据错乱的概率比较高,在不同的板子上一致性也不好。如果MCU的电平翻转速度达不到纳秒级,这种方法必失败。 2. PWM+DMA驱动也是我采用的方法。我们知道每一位的特征周期为1.25us。这个间隔对应于800kHz的频率。此外,仔细观察协议,我们可以注意到唯一改变的是每个周期的高部分。它类似于一个脉冲宽度调制信号,可以做一个800Khz的PWM波去驱动。 理论上说到这里灯就已经可以亮起来了,但我还是引入了DMA,简单来说,DMA 传输将数据从一个地址空间复制到另外一个地址空间。当CPU 初始化这个传输动作,传输动作本身是由 DMA 控制器来实行和完成。DMA的数据传输不占用CPU。 想象一下,当CPU传输成百上千个LED的数据,突然有中断发生,那么这组数据就会发生传输错乱。而当数据量很大时,CPU的占用率会非常高,这样就不能执行其他任务了。DMA可以把CPU解放出来。
看看代码:
代码后面会发,面对小白向的旁友,为了尽快驱动起来,我就说一下包装好的函数:
WS2812_ledsingle_send1(uint8_t color[][3], uint8_tcolor[][3]):
这个函数有两个参数:
uint8_t color[][3]:这个是一个N*3的数组,N就是颜色组数,{R,G,B}3个数就是RGB。
大概长这样: uint8_t myrgb[9][3]={{0,0,0},{32,0,0},{32,0,0},{32,0,0},{32,0,0},{32,0,0}, {32,0,0},{32,0,0},{32,0,0}}
不过这里有个BUG,我发现前几帧可能会被吞掉,为了保证稳定,第一个数组为空.
写完了之后灯就可以亮起来了。
|