利用stm32cubeide实现几个功能:
1.跑马灯
2.单色呼吸灯
ws2812b就不介绍了,不懂得参考这个(39条消息) 初出茅庐的小李第84篇博客之驱动WS2812B灯带(一)_初出茅庐的小李的博客-CSDN博客_ws2812b知道控制原理后,在软件里面配置引脚,我这里用的是PA8。
模式设置推挽输出,速度设置为HIGH,其他得没啥了,生成代码。
要想实现以上三个功能,首先我们得先让ws218b亮起来,根据时序图,编写我们的发送函数。
#define T0H() __NOP();__NOP();__NOP();__NOP();
#define T0L() __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
#define T1H() __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
#define T1L() __NOP();__NOP();__NOP();__NOP();
void WS2812_Send(uint8_t data){
for(uint8_t i=0;i<8;i++){
if(data & 0x80){
GPIOA->BSRR = GPIO_PIN_8;
T1H();
GPIOA->BRR = GPIO_PIN_8;
T1L();
}
else{
GPIOA->BSRR = GPIO_PIN_8;
T0H();
GPIOA->BRR = GPIO_PIN_8;
T0L();
}
data<<=1;
}
}
通过该函数可以写入一个颜色的数据,要想使彩灯亮起来,就需要发送三个颜色的数据。当然一般来说不会只有一个ws2812,我这里用到了24个,所以想让他们全部亮起来的话需要发送24次。
现在我们思考一个问题,由于ws2812是串在一起的,想要实现跑马灯的效果,不能对每个灯进行单独控制。
所以我采取的方法是把上一个灯的颜色设置为0,这样子就只有当前要显示的灯才有颜色。废话不多说看程序
void ws218_Clear(uint8_t num){ //清除颜色
for(int j=0;j<num;j++){
for(int i=0;i<3;i++)
WS2812_Send(0x00);
}
}
void waterfall_light(uint8_t green,uint8_t red,uint8_t blue){
for(int i=0;i<24;i++){ //因为有24个灯所以要发12次
for(int j=0;j<i;j++){ //把上一个灯颜色清掉
ws218_Clear(1);
}
WS2812_Send(green); //发送当前需要亮的灯的颜色
WS2812_Send(red);
WS2812_Send(blue);
HAL_Delay(500);
}
ws218_Clear(24); //把全部颜色都清掉
HAL_Delay(1);
}
这样就可以实现跑马灯效果了。
现在我们来实现呼吸灯,实现呼吸灯大部分都是通过pwm来改变输出,实现呼吸的效果,但是由于ws2812的控制方式,使得这种方式对于我们来说不可行,所以经过网上查找资料得知,可以把RGB转换成HSL,通过改变L的大小来实现亮度的变化,在把HSL转换成RGB显示出来。
具体转化代码请参考(39条消息) HSL和RGB的相互转换_qq_1769172560的博客-CSDN博客_hsl转rgb
解决了调节亮度问题这样就可以来编写我们的呼吸灯代码了
double luminance;
void breathing_light(uint8_t green,uint8_t red,uint8_t blue){ //呼吸灯 rgb单色的呼吸;
RGB2HSL(green,red,blue,&H,&S,&L); //将rgb转换成HSL
luminance=L;
while(luminance>=0){
HSL2RGB(H,S,luminance,&r,&g,&b); //将hsl转换成rgb
for(int i=0;i<24;i++){
WS2812_Send(r);
WS2812_Send(g);
WS2812_Send(b);
}
luminance-=0.01;
HAL_Delay(12);
}
luminance=0;
while(luminance<L){
HSL2RGB(H,S,luminance,&r,&g,&b);
for(int i=0;i<24;i++){
WS2812_Send(r);
WS2812_Send(g);
WS2812_Send(b);
}
luminance+=0.01;
HAL_Delay(12);
}
}
我们只需要在main函数中调用就可以了。效果这里就不展示了。