简介

数据手册可于此处下载

  • WS2812的单像素点由RGB芯片与LED封装原件组成,其中RGB芯片IC为WS2811。
  • 每个像素点均可以显示RGB各256级颜色,共16777216种颜色。
  • 内置锁存电路保证数据切换的稳定、上电/掉电复位电路。
  • 每个像素点读取24bit的数据,并将余下的数据继续转发到下一个像素点。
  • 在读取24bit的数据时,遵守GRB的顺序由高位到低位。

通信时序

WS2812的通信使用单线通信协议,DIN为数据输入,DOUT可以连接下一个像素点的DIN做到数据转发,如图:

在通信中,规定的0/1时序如下。(当然我找了十来份数据手册,其中的时序参考时间均不同。)

示例

在STC15 12M的频率下一个_nop_();对应的时间为1/12us。但是请注意在C51中语句的跳转仍然占用大量时间,使用较低频率的晶振会使得时序误差的扩大,直接表现为无法驱动WS2812,这也是很多性能较低的单片机无法驱动WS2812的原因。因此我使用了24M晶振,定义NOP为6个_nop_();,即0.25us。无论如何请注意延时的问题,否则WS2812无法被正常驱动。

  • 初始化:
1
2
3
4
#include <stc15f2k60s2.h>
#include <intrins.h>
#define NOP {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}
sbit DIN=P1^0;
  • WS2812初始化:
1
2
3
4
5
6
7
8
9
10
//拉低DIN保持50us以上
void ws2812_init()
{
uchar i;
DIN=0;
for(i=0;i<=200;i++)
{
NOP;
}
}
  • WS2812写低电平:
1
2
3
4
5
6
7
8
9
10
11
//高电平0.25us,低电平1us
void ws2812_write_low()
{
DIN=1;
NOP;
DIN=0;
NOP;
NOP;
NOP;
NOP;
}
  • WS2812写高电平:
1
2
3
4
5
6
7
8
9
10
11
//高电平1us,低电0.25us
void ws2812_write_high()
{
DIN=1;
NOP;
NOP;
NOP;
NOP;
DIN=0;
NOP;
}
  • WS2812写字节:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void ws2812_write_byte(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
if(dat&0x80)
{
ws2812_write_high();
}
else
{
ws2812_write_low();
}
dat<<=1;
}
}
  • WS2812写RGB数据:
1
2
3
4
5
6
void ws2812_write_rgb(uchar r,uchar g,uchar b)
{
ws2812_write_byte(g);
ws2812_write_byte(r);
ws2812_write_byte(b);
}
  • WS2812写24Bit的颜色数据,由于写rgb函数的参数为uchar,因此会自动裁剪dat:
1
2
3
4
5
6
void ws2812_write_24bits(ulong dat)
{
ws2812_write_byte(dat>>8); //write_r
ws2812_write_byte(dat>>16); //write_g
ws2812_write_byte(dat); //write_b
}

效果

在主函数中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void main()
{
init_sys();
ws2812_init();
ws2812_write_24bits(0x000000);
ws2812_write_24bits(0xff0000);
ws2812_write_24bits(0x00ff00);
ws2812_write_24bits(0x0000ff);
ws2812_write_24bits(0xffff00);
ws2812_write_24bits(0xff00ff);
ws2812_write_24bits(0x00ffff);
ws2812_write_24bits(0xffffff);
while(1)
{

}
}

效果如图:

其它

WS2812灯光效果

WS2812驱动总结