幻彩LED WS2812B
WS2812B 有三个状态,0码和1码 则是在通讯的时候表示0,或者1的状态。
当需要复位LED 灯的时候,则需要使用reset码将LED灯 控制为熄灭的状态。
下面表示了三个码的时间,这个在GPIO模拟的时候,需要特别注意,GPIO翻转的速度。可以通过逻辑分析仪来读取实际GPIO的控制信号翻转速度。
下图是单个24bit的数据顺序,
主机会不断的刷新数据,然后逐个传递下去
1. 硬件连接
这边硬件上使用了PA13 这个PIN来控制灯的信号。 因为WS2812B,这个芯片是串行的总线,所以只需一个GPIO,就可以控制所有连接的LED灯。
2. CubeMX生成代码
可以看到,配置了3个部分
- 外部时钟
- SWD 接口
- GPIO 配置成输出模式
注意:下图是配置的PB7,板子上需要配置成PC13
系统时钟72M,需要和图片保持一致
点击 GENERATE CODE 生成代码
3. 编写代码
3.1 WS2812B 控制相关的代码
下面就是控制WS2812B的代码,其中 “__NOP();” 数量是根据芯片的频率,以及LED的时序要求来调整的。如果跟换芯片,需要自己调整数量。
WS2812B控制代码
c
#define GPIO_WS2812B GPIOC
#define GPIO_PIN_WS2812B GPIO_PIN_13
//存储一个转化后的RGB2进制数 共24bits
struct My_24bits //结构体
{
unsigned char G_VAL; //绿色 0-255
unsigned char R_VAL; //红色 0-255
unsigned char B_VAL; //蓝色0-255
};
struct My_24bits RGB;
/*写入数据时序*/
void Send_A_bit(unsigned char VAL)
{
if (VAL!=1)
{
GPIO_WS2812B->BSRR = GPIO_PIN_WS2812B;
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
GPIO_WS2812B->BSRR = (uint32_t)GPIO_PIN_WS2812B << 16u;
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
}
else
{
GPIO_WS2812B->BSRR = GPIO_PIN_WS2812B;
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
GPIO_WS2812B->BSRR = (uint32_t)GPIO_PIN_WS2812B << 16u;
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
}
}
void Reset_LED()
{
HAL_GPIO_WritePin(GPIO_WS2812B,GPIO_PIN_WS2812B, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIO_WS2812B,GPIO_PIN_WS2812B, GPIO_PIN_RESET);
HAL_Delay(1);
}
/*发送24位字符(包含RGB信息各8位)*/
void Send_24bits(struct My_24bits RGB_VAL)
{
unsigned char i;
for(i=0; i<8; i++)
{
Send_A_bit(RGB_VAL.G_VAL>>(7-i)&0x01);//注意是从高位先发
}
for(i=8; i<16; i++)
{
Send_A_bit(RGB_VAL.R_VAL>>(15-i)&0x01);
}
for(i=16; i<24; i++)
{
Send_A_bit(RGB_VAL.B_VAL>>(23-i)&0x01);
}
}
一个“Send_24bits”,就是点亮一个LED灯,如果需要点亮多个,则发送多次就可以了。
C
while (1)
{
RGB.G_VAL = 0; RGB.R_VAL = 0;RGB.B_VAL = 255;
Reset_LED();
Send_24bits(RGB);
Send_24bits(RGB);
Send_24bits(RGB);
Send_24bits(RGB);
Send_24bits(RGB);
Send_24bits(RGB);
Send_24bits(RGB);
Send_24bits(RGB);
}
循环改变LED灯的颜色
C
RGB.G_VAL = 0; RGB.R_VAL = 0;RGB.B_VAL = 0;
int i = 0;
char flag = 0;
while()
{
i++;
if(flag == 0)
{
RGB.B_VAL = 255 -i;
RGB.R_VAL = i;
if(i == 255)
{
i =0;
flag = 1;
}
}else if(flag ==1)
{
RGB.R_VAL = 255 -i;
RGB.G_VAL = i;
if(i == 255)
{
i =0;
flag = 2;
}
}else if(flag ==2)
{
RGB.G_VAL = 255 -i;
RGB.B_VAL = i;
if(i == 255)
{
i =0;
flag = 0;
}
}
HAL_Delay(1);
}
4. 后记
- 可以在代码中循环调整灯的颜色,从而实现颜色变化,---------待完善
- 单个GPIO可以实现多灯的控制,如果没有刷新速度的要求,则可以做低刷新速度的屏幕