STM32SPI驱动WS2812
前言
本文将介绍怎么使用STM32的SPI接口来驱动WS2812模块。如果有说明不完全或者有错误的地方,欢迎指正,一切请以官方手册为准。
WS2812简介
在学习单片机控制LED灯过程中,如果我要控制LED发出不同颜色的光,通常需要使用RGB LED灯。按正常逻辑就需要三个PWM通道来控制红绿蓝三种颜色的亮度,但是如果我要控制多个RGB LED灯,使用的PWM通道数量就会成倍增加,对于灯条等需要控制大量LED的场景来说,这种方式显然不太现实。WS2812就是一款集成了控制芯片的RGB LED灯,每个LED灯都可以通过单线串行通信来控制,这样就大大减少了需要的PWM通道数量,非常适合需要控制大量LED的场景。
WS2812的通信协议
WS2812使用单线串行通信协议,每个LED灯需要24位数据来控制颜色,其中8位控制红色亮度,8位控制绿色亮度,8位控制蓝色亮度。数据传输的时序非常严格,具体如下:
其中1和0的区别在于高电平持续的时间
这张图非常重要,理解了这张图才能看懂接下来的SPI模拟WS2812协议的内容
使用SPI模拟WS2812协议
由于WS2812的通信协议时序非常严格,直接使用GPIO模拟可能会比较麻烦,尤其是在需要控制大量LED的情况下。幸运的是,我们可以使用STM32的SPI的MOSI来模拟WS2812的通信协议。结论先行,我们目的是用SPI一个数据位(8bits)来模拟WS2812的一个码元(1bit)。
计算SPI的时钟频率
- 根据WS2812的通信协议,0的高电平持续时间为220ns
380ns,1的高电平持续时间为580ns1us,低电平持续时间均为580ns1us。且一个码元至少持续1250ns。综上,一个WS2812码元的周期范围为1250ns2000ns,频率为500kHz~800kHz。 - 前面有提到,我们是用SPI一个数据位(8bits)来模拟WS2812的1个码元,故一个SPI数据位的周期为1250ns
2000ns,频率为500kHz800kHz。 - SPI的时钟频率是数据位频率的8倍,所以SPI的时钟频率范围为4MHz~6.4MHz,理论来说在这个范围内都可以正常工作,但建议不要太接近上限,以免出现时序问题。本文中我选择参考达妙MC-02开发板例程,将SPI时钟频率设置为6MHz。
SPI数据位编码
根据WS2812的通信协议,00的高电平持续时间为220ns380ns,1的高电平持续时间为580ns1us,低电平持续时间均为580ns~1us。
根据上述SPI的时钟频率选择6MHz,SPI1个bit周期为166.67ns,可以算出:
- 0码元:高电平持续2位,低电平持续6位
- 1码元:高电平持续4位,低电平持续4位
但是由于WS2812只是借用了SPI的MOSI线来传输数据,并不是真正的SPI通信,所以在发送数据第一个bit时,数据可能会粗糙不稳定,为了保证第一个bit的稳定性,我们可以把所有要发送的数据右移1位,这样就相当于在数据前面添加了一个0码元,保证了第一个bit的稳定性。
最终的SPI数据位编码如下:
- 0码元:0b0110 0000 = 0x60
- 1码元:0b0111 1000 = 0x78
- RES:0b0000 0000 = 0x00
程序
我使用的是达妙MC-02开发板,时钟树及SPI配置如下:

注意:
- SPI的时钟频率必须在4MHz~6.4MHz之间
- 空闲时要为低电平
控制一个WS2812的的参考代码如下:
1 |
|
其中三个参数分别为RGB三种颜色的亮度,范围为0~255
控制多个WS2812
如果需要控制多个WS2812,只需要把每个LED灯的数据依次发送出去即可,WS2812会自动把数据传递给下一个LED灯,最后在一起发送RES码元来完成数据的刷新,上述代码加入循环即可解决,比较简单,不过多赘述。
结语
通过上述方法,我们就可以使用STM32的SPI接口来驱动WS2812模块了。需要注意的是,WS2812的通信协议时序非常严格,如果出现闪烁或者颜色不正确的情况,可能是时序问题导致的,可以尝试调整SPI的时钟频率或者数据位编码来解决。另外,如果需要控制多个LED灯,可以按照WS2812的通信协议,把每个LED灯的数据依次发送出去即可,WS2812会自动把数据传递给下一个LED灯,非常方便。
- 标题: STM32SPI驱动WS2812
- 作者: HeWenXuan
- 创建于 : 2026-02-18 22:12:47
- 更新于 : 2026-02-18 22:12:47
- 链接: https://redefine.ohevan.com/2026/02/18/ws2812/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。