WS2812 控制脉冲
01 WS2812彩色灯珠
一、前言
WS2812是一个是靠单条通信信号线进行控制的智能集成彩色 LED 灯柱, 仅仅通过单片机的一条 IO 线 便可以完成对多个级联的WS2812色彩的控制。 根据它数据手册, 通讯协议是一个非常简单的单线、单向通行协议。 依靠脉冲高电平的宽度发送 0 和 1,。 它的数据手册给出了 0, 1 电平的脉冲宽度规格, 下面通过实际测量来确定一下这些时间参数的范围, 为之后控制 WS2812提供数据支撑。
▲ 图1.1.1 WS2812 彩色灯珠
二、测量方案
测试方法是在面包板上搭建的测试电路。 产生测试脉冲的单片机是 STC32F12 LQFP32 封装的单片机。 三个待测试级联的WS2812灯珠是从一个购买到的彩色灯带上剪裁下来的灯珠, ·焊接有简单的接口, 便于在面包板上进行测试。
利用对 STC32F12 的 IO 口 软件编程, 通过一个子程序输出控制 WS2812 控制波形。 根据输出 0,1 的要求, 分别控制 IO 口高低电平的时间范围, 最终通过观察级联在一起的三个 LED灯珠是否按照规定的顺序进行变色, 最终来确定通讯协议是否能够控制 WS2812, 最终, 利用示波器测量脉冲的时间参数。
三、测量结果
首先测试一下脉冲低电平的时间范围。 对于0,1 两种脉冲信号, 数据手册给出的时间分别为 0.85微秒和0.4微秒, 时间误差范围是正负 0.15微秒。 由于复位脉冲, 也被称作回车脉冲时间规定为超过 50微秒, 所以, 我们猜测数字脉冲的低电平最多不能够超过 50微秒。 在程序中, 使用 DelayUS 函数来确定低电平的时间。 由于处在程序循环中, 所以实际的低电平比起 DelayUS 的延迟还是略微多一些时间。 这是将 0, 1 数字脉冲 的低电平直接设置为 50微秒, 可以看到三个 WS2812仍然可以工作。 利用示波器的光波测量功能, 可以看到相邻l个脉冲之间的时间已经为 51.7微秒, 如果将延迟的时间增加超过 51微秒, 此时可以看到三个灯珠已经不受控制了, 特别是最后一个WS2812不改变颜色了。 如果将时间改为 49微秒, 可以观察到三个灯珠工作正常。 由此可见, WS2812对于低电平的时间要求非常宽松, 也就是无论对于数字1, 还是数字0, 它们的低电平的时间长度只要不超过 50微秒都可以。
▲ 图1.3.1 低电平时间最长不允许超过 50微秒
利用程序修改低电平的持续时间, 可以看到当低电平时间过小也不行, 经过实际测量可以知道, 当低电平时间超过 375ns之后, WS2812便可以正常工作了。
下面测试高电平时间范围, 数据手册中要求数字1,0 的高电平分别为 0.4, 0.85 微秒; 那么这个 时间范围是否也可以调整? 在这里通过修改NOP参数, 来测试高电平的时间范围。 分别测试0,1两种波形对应的时间范围。
对于数字0所对应的高电平时间, 通过调整软件中的参数, 可以看到当它的时间不超过 468ns的时候, WS2812还可以被正常控制, 稍微在延长的时候, 所有的脉冲都被当成 1 脉冲了。
对于数字1 对应的高电平时间, 显然它的下限就是数字0 对应的高电平的上限, 也就是不能够小于 470ns。 否则就会被等长 0。 下面测试它对应的时间长度上限, 这里使用 DelayUS 函数来设置数字 1 对应的高电平的上限, 经过测试, 可以看到这个时间仍然需要不超过 50微秒, 也就是与低电平的上限是差不多一致的。 由此, 我们可以得到 WS2812 控制脉冲的时间范围, 也就是在周期不超过 50微秒的范围内, 脉宽小于 470ns 的脉冲为 0, 宽度在470ns 至 50微秒之间的都被当做1。 ·这个脉冲范围是相当的宽泛。 很多的单片机都比较容易实现控制 WS2812彩色灯珠。
※ 总 结 ※
本文利用单片机 STC32F12 测量了 WS2812 彩色灯珠控制脉冲波形时间参数, 可以看到实际上波形时间参数非常宽泛, 远远超过它的数据手册给定的范围。 不过,从实际控制角度来看, 为了实现WS2812控制更加丝滑, 这些时间参数基本上都尽量靠近它们参数范围的下限。 也就是越快越好。
void main(void) {
unsigned int nCount, nSendCount;
float f1, f2, f3;
MainInit();
PM_PP(LED);
OFF(LED);
PM_PP(SPIO);
OFF(SPIO);
nCount = 0;
nSendCount = 0;
for(;;) {
WaitTime(1);
if(++nSendCount > 250) {
nSendCount = 0;
ON(LED);
NOP(40);
f1 = nSendCount;
f2 = 1.2334;
f3 = atan(f1*f2);
OFF(LED);
}
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 ++) {
a = c & ucMask;
ucMask >>= 1;
ON(SPIO);
if(a > 0) DelayUS(45);
else NOP(5);
OFF(SPIO);
DelayUS(2);
}
}
EA = 1;
}
■ 相关文献链接:
● 相关图表链接: