1,实物展示
WS2812是一种可编程的LED灯,具有RGB显示效果,可显示的颜色数量为2^24
红色:+5V
白色:GND
绿色:数据输入
2,引脚定义与电气属性
VDD:电源正,范围+3.5V~+5.3V
VSS :电源地
DIN:输入输入端,电压范围-0.5V ~ VDD+0.5V
DOUT:数据输出端,电压范围-0.5V ~ VDD+0.5V
单片机数据从DIN进入第一个灯珠时,第一个灯珠会锁存第一个24位数据,然后剩下的数据会从灯珠DOUT引脚输出到下一个灯珠的输入端,依此类推,可达到单总线控制多个灯珠的目的。
值得一提的是,如果使用的是3.3V的单片机,是不能直接驱动WS2812,需要接5V的上拉电阻,然后设置IO口为开漏输出模式,这样才能满足WS2812的电平协议,可能也不用,具体还是自行测试一下。
3,时序分析
该通讯方式为单总线通信,即利用高低电平的持续时间来确定0和1,与我们之前学的DS18B20温度传感器类似。
简单说就是,在一个周期内,高电平和低电平的比例,确定了数据帧为0、还是为1
下面的是数据帧的组成部分:
数据帧为1:高电平持续T1H,低电平持续T1L
数据帧为0:高电平持续T0H,低电平持续T0L
复位帧:电平持续时间大于280us
复位帧可以理解为一个结束符号,让灯带知道我们需要操作LED灯的个数,例如我们只需要操作10个灯珠,但是我们有20个灯珠,这时候我们在第十个指令后面加个复位帧,就可以只控制前面10个灯,而不会控制后面的灯,当然前提是灯珠首位相连。
通常情况下,我们设置一个通信周期为800khz,即1250ns
短的持续时间为300ns、长的持续时间为850ns,
这样设置是为了方便STM32单片机使用PWM模式+DMA请求来驱动WS2812灯带。
注意一点就是,如果使用传统的51单片机是不能驱动WS2812,除非使用的是1T的单片机,如果是12T的51单片机,则不能进行控制。
一个LED灯需要24位来控制,即三个字节,每个字节代表的是不同的RGB,我们通过输入不同的数值,来控制不同的颜色,其实RGB是我们自然界的三大颜色,其他颜色实际都是这三个原色的组合。
4, 色域表
5,编程实战
①基于STC8H8K64U———24Mhz
使用__nop_()函数作为延时,已知SCT8H单片机作为1T单片机,使用的时钟频率是不需要分频的,此时,机械周期等于时钟振荡周期。
所以单片机的机械周期为𝑇0=1/24𝑀h𝑧≈41𝑛𝑠, 即调用一次nop()的时间为41ns。
由于单片机指令执行需要一定的时间,所以我们的设定值要略小一点。
值得一提的是,该单片机与我们熟知的STC15系列是完全兼容的,所以也可以使用ST15单片机进行开发。
ws2812.c文件
#include "ws2812.h"
#define Led_Pin P14
void WS2812_SendData(unsigned char R,unsigned char G,unsigned char B)
{
unsigned char i,j,temp[3];
temp[0]=G;
temp[1]=R;
temp[2]=B;
for(j=0;j<3;j++)
{
for(i=0;i<8;i++)
{
if(temp[j] & (0x80>>i)) //发送1
{
Led_Pin=1;
_nop_();_nop_();_nop_();_nop_();_nop_();//_nop_(); delay 41ns
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
Led_Pin=0;
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();
}
else //发送0
{
Led_Pin=1;
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();
Led_Pin=0;
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
}
}
}
}
void delay_ms(unsigned int ms) //@24.000MHz
{
unsigned char i, j;
while(ms--)
{
i = 24;
j = 85;
do
{
while (--j);
} while (--i);
}
}
ws2812.h文件
#ifndef __WS2812_H
#define __WS2812_H
#include <STC8H.H>
#include "intrins.h"
void WS2812_SendData(unsigned char R,unsigned char G,unsigned char B);
void delay_ms(unsigned int ms); //@24.000MHz
#endif
mian.c文件
#include <STC8H.H>
#include "ws2812.h"
void main()
{
P1M1=0x00; //准双向IO口模式
P1M0=0x00;
while(1)
{
WS2812_SendData(255,0,0);
WS2812_SendData(0,255,0);
WS2812_SendData(0,0,255);
delay_ms(10);
}
}
值得一提的是,如果是STC8H系列单片机的话,我们在使用引脚之前,都要进行初始化,因为该系列单片机的默认模式为悬空模式,这点与普通的51单片机有很大区别。
对您有帮助的话,请点个赞吧!!