视频链接:

QQ交流群
1050110856
项目简介
使用USB转串口芯片来驱动WS2812,实现电脑控制WS2812的功能。
项目参数
- 使用CP2102N芯片,该芯片波特率能够达到3Mhz
- 使用NMOS将TX的电平翻转
原理解析
一句话概括,就是使用串口来模拟WS2812的时序,重点是在软件部分。


- 上面两张图片分别是WS2812的时序和串口8N1模式下的时序,可以看到WS2812的0码和1码就是由长短不同的高低电平组成,0码就是短低电平加上长高电平,1码就是长高电平加上短低电平,我们发现这里的长短电平基本符合1:3的关系。
- 当我们把串口波特率设为3Mhz后,串口的最小高电平脉冲就是333ns,刚好满足WS2812的较短电平的时序,那么再加上三倍的反向电平,就能够组成2812的一个bit。
- 所以我们想办法将串口发出的数据变成这种1:3的脉冲,就能够驱动WS2812了。
- 要注意串口是存在固定的起始位和停止位的,做数据转换的时候要考虑进去
- 注意串口空闲时是高电平,加上MOS管后变为低电平,可以作为复位信号,这也是为什么必须要将电平翻转的原因。
关键代码
/// 位打包函数
/// 串口必须是8N1协议,起始位固定为0,停止位固定为1,无校验位,一个字节10bit。
/// 将串口的TX用MOS管进行电平翻转
/// 将D0D1D2置为1,加上起始位就是0111,翻转后可以作为0码,将D3D4D5D6置为0001,反转后就是1码。
/// 将D0D1D2置为001,加上起始位就是0001,翻转后可以作为1码,将D3D4D5D6置为0111,反转后就是0码。
/// 将D7置为1,加上停止位加上字节间隙作为空闲位,空闲位小于50us。
/// 串口空闲时默认高电平,翻转后就是低电平,可以作为复位信号
///
/// 要编码的字节数据
/// 输出缓冲区
/// 当前位位置(引用传递)
private static void WS2812PackBits(byte data, byte[] output, ref int bitPos)
{
for (int i = 0; i < 4; i++)
{
byte code = (byte)(((data & 0x80) != 0 ? 0x04 : 0x07) | ((data & 0x40) != 0 ? 0x40 : 0x70) | 0x80);
output[bitPos] = code;
bitPos++;
data <<= 2;
}
}Code language: JavaScript (javascript)
上面代码的功能是将一个字节的RGB数据转化为串口数据,分别对R,G,B数据进行转换后就能够得到一个灯珠的RGB驱动数据。
private static void WS2812EncodeLed(WS2812Color color, byte[] buffer)
{
if (buffer.Length < 12)
throw new ArgumentException("Buffer must be at least 12 bytes long");
int bitPos = 0;
Array.Clear(buffer, 0, 12); //
WS2812PackBits(color.Green, buffer, ref bitPos);
WS2812PackBits(color.Red, buffer, ref bitPos);
WS2812PackBits(color.Blue, buffer, ref bitPos);
}Code language: JavaScript (javascript)
完整项目见github链接:
(https://github.com/pandereyes/UART_TO_WS2812)
借助AI完成的,目前功能还比较少,后续希望和大家一起完善。
附件为测试上位机。
注意事项
1. 目前版本直接从电脑USB取电,对灯板的驱动能力取决于电脑USB的输出能力,所以会遇到灯板亮度过高卡死的情况。后续我会出一个带额外供电的版本。
- 注意正负极,别接反了
实物图

