STCF12控制W2812
01 W2812灯珠
一、前言
W2812 LED 灯珠内部集成了三色 LED的驱动电路, RGB LED 的亮度可以独立控制, 分成 256级。 使用一个串行数据性可以控制多个W2812的颜色。 特殊定义的数据通讯协议, 使用了脉冲宽度来表示 0 和 1, 当高电平宽度大于 550ns 以上时, 对应的是 1, 否则是 0。 利用一个超过 50微秒的低电平来结束通讯。 W2812具有一个接受和发送 IO口, 可以实现多个 LED的级联。 每 24 个bite 确定串行中 一个 W2812的颜色, 从前往后 每 八个 bit 分别定义了 绿、红、蓝的亮度。 当超长的 低电平来的时候, 所有的 W2812可以同时改变颜色。 这样就可以使用一条 IO 口来控制一整条等待 W2812的颜色了。
▲ 图1.1.1 W2812灯珠
二、测试效果
最近新出的 STCF12 单片机, 时钟频率已经可以达到 64MHz, 利用它的 IO 口 可以输出控制 W2812串口数据。 这样便可以应用一条 STCF12的 IO 线来控制W2812灯柱。 这是实现 W2812控制程序。
输入参数 pBuffer, 预先存储有RGB数值, 每三个为一组控制 一个 W2812彩色亮度。 通过一个循环输出 Buffer 中所有字节的内容。 利用 Mask 右移位值,获得输出数值的每一位, 根据该位数值为 0 还是 1, 分别控制输出脉冲的高电平。 这里这里使用 NOP的多少来完成脉冲宽度的定时。 为了防止单片机中断影响输出位的数值, 在这段循环前将单片机中断关掉。 这是输出控制信号的核心程序。 非常简单。 依靠着 STC32F12 单片机的速度, 实现了W2812串行通讯信号。
STC32F12 IO 端口输出信号直接连接在第一个 W2812的 输入端口, W2812的输出信号连接到下一LED, 这是示波器显示 W2812输出的脉冲信号, 可以看到它是将 STC32FF12输入的信号进行了重新整形输出, ·对比一下可以看到对应的高电平比 STC32F12输出信号变窄了。 信号的周期并没有改变。 这是利用STCF12控制三个 W2812的效果。 如果 W2812比较多, 可以将W2812分成若干组, 进行并行控制。
这里对比着第一个 W2812 和第二个 W2812 数据波形, 可以看到每经过24个脉冲之后, 第一个W2812将会输出它存储的脉冲宽度。 这是第三个 W2812的数据波形, 它的数据是由第二个W2812输出的。 所以它比第一个 W2812 完了 48个脉冲。 通过这样, 可以将很多 W2812进行级联。 理论上将, 可以控制无穷多个W2812的串联。
※ 总 结 ※
本文测试了STC32F12 控制W2812彩色灯珠, 利用一个STC32F12的 IO 端口可以控制一组级联在一起多个 W2812彩色灯珠。 这也彰显了STC32F12 的高速运行的特色。
一、测试程序
void main(void) {
unsigned int nCount, nSendCount;
unsigned char ucRGB[9];
unsigned char ucRGBCount;
MainInit();
PM_PP(LED);
OFF(LED);
PM_PP(SPIO);
OFF(SPIO);
nCount = 0;
nSendCount = 0;
for(;;) {
if(++nCount & 0x1) ON(LED);
else OFF(LED);
WaitTime(1);
if(++nSendCount > 250) {
nSendCount = 0;
OutW2812RGB(ucRGB, sizeof(ucRGB));
if(ucRGBCount == 0) {
ucRGB[0] = 0xff;
ucRGB[1] = 0x00;
ucRGB[2] = 0x00;
ucRGB[3] = 0x00;
ucRGB[4] = 0xff;
ucRGB[5] = 0x00;
ucRGB[6] = 0x00;
ucRGB[7] = 0x00;
ucRGB[8] = 0xff;
} else if(ucRGBCount == 1) {
ucRGB[0] = 0x00;
ucRGB[1] = 0xff;
ucRGB[2] = 0x00;
ucRGB[3] = 0x00;
ucRGB[4] = 0x00;
ucRGB[5] = 0xff;
ucRGB[6] = 0xff;
ucRGB[7] = 0x00;
ucRGB[8] = 0x00;
} else {
ucRGB[0] = 0x00;
ucRGB[1] = 0x00;
ucRGB[2] = 0xff;
ucRGB[3] = 0xff;
ucRGB[4] = 0x00;
ucRGB[5] = 0x00;
ucRGB[6] = 0x00;
ucRGB[7] = 0xff;
ucRGB[8] = 0x00;
}
ucRGBCount ++;
if(ucRGBCount >= 3) ucRGBCount = 0;
}
ConsoleDebug();
}
}
void MainInit(void) {
C251Init();
STC32FInit();
ControlInit();
SerialTxtInit();
WaitTime(500);
print("C251 -- by Dr. ZhuoQing,%s,%s[%bd]\r\n\r\n", "\n", __DATE__, "\n", __TIME__, "\n", WTST);
}
void OutW2812RGB(unsigned char * pBuffer, unsigned char ucLength) {
unsigned char i, j, ucMask, c, a;
EA = 0;
for(i = 0; i < ucLength; i ++) {
ucMask = 0x80;
c = *(pBuffer + i);
for(j = 0; j < 8; j ++) {
D
a = c & ucMask;
ucMask >>= 1;
ON(SPIO);
if(a > 0) NOP(30);
else NOP(10);
OFF(SPIO);
if(a > 0) NOP(5);
else NOP(15);
}
}
EA = 1;
}
#define LED 1,0
void OutW2812RGB(unsigned char * pBuffer, unsigned char ucLength);
■ 相关文献链接:
● 相关图表链接: