标题:
单片机+WS2812控制LED灯算法请教,从中间往两边跑,以及多种效果
[打印本页]
作者:
kxcuser
时间:
2021-11-10 11:44
标题:
单片机+WS2812控制LED灯算法请教,从中间往两边跑,以及多种效果
如何我要从中间往两边跑,以及多种效果,请教下算法思路,现在就三种流法,也可以说是两种
单片机源程序如下:
#include<STC8H1K28.H>
#include"intrins.h"
sbit WS2812 = P1^0;
sbit on = P2^4;
#define numLEDs 36 //灯的个数
unsigned char buf_R[numLEDs] = {0};//颜色缓存
unsigned char buf_G[numLEDs] = {0};
unsigned char buf_B[numLEDs] = {0};
void RGB_Set_Up(); //送0码
void RGB_Set_Down(); //送1码
void HAL_Delay(unsigned long t)
{
unsigned int x,y;
for(x=114;x>0;x--)
for(y=t;y>0;y--);
}
//复位延时
void Delay50us() //@22.1184MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 2;
j = 15;
do
{
while (--j);
} while (--i);
}
//1码,高电平850ns 低电平400ns 误差正负150ns
void RGB_Set_Up()
{
WS2812 = 1;//经过逻辑分析仪调试的的延时
_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
WS2812 = 0;
}
//1码,高电平400ns 低电平850ns 误差正负150ns
void RGB_Set_Down()
{
WS2812 = 1;//经过逻辑分析仪调试的的延时
_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
WS2812 = 0;
}
//发送24位数据
void Send_2812_24bits(unsigned char G8,unsigned char R8,unsigned char B8)
{
unsigned int n = 0;
for(n=0;n<8;n++) //发送G8位
{
G8<<=n;
if(G8&0x80 == 0x80)
{
RGB_Set_Up();
}
else
{
RGB_Set_Down();
}
}
for(n=0;n<8;n++)//发送R8位
{
R8<<=n;
if(R8&0x80 == 0x80)
{
RGB_Set_Up();
}
else
{
RGB_Set_Down();
}
}
for(n=0;n<8;n++)//发送B8位
{
B8<<=n;
if(B8&0x80 == 0x80)
{
RGB_Set_Up();
}
else
{
RGB_Set_Down();
}
}
}
//复位码
void RGB_Rst()
{
WS2812 = 0;
Delay50us();
}
//颜色交换24位不拆分发
void SetPixelColor(unsigned char num,unsigned long c)
{
unsigned char i;
for(i=0;i<numLEDs;i++)
{
buf_R[num] = (unsigned char)(c>>16);
buf_G[num] = (unsigned char)(c>>8);
buf_B[num] = (unsigned char)(c);
}
for(i=0;i<numLEDs;i++)
{
Send_2812_24bits(buf_G[i],buf_R[i],buf_B[i]);
}
}
//复位
void PixelUpdate()
{
RGB_Rst();
}
// Fill the dots one after the other with a color
//用一种颜色填充这些圆点
void colorWipe(unsigned long c, unsigned int wait)
{
unsigned char i=0;
for( i=0; i<numLEDs; i++)
{
SetPixelColor(i, c);
PixelUpdate();
HAL_Delay(wait*5);
}
}
void Watercolor(unsigned long c, unsigned int wait)
{
unsigned char i=0;
for( i=0; i<numLEDs; i++)
{
SetPixelColor(i, c);
PixelUpdate();
HAL_Delay(wait*5);
SetPixelColor(i, 0);
PixelUpdate();
HAL_Delay(wait);
}
}
void main()
{
P1M0=0xFF;
P1M1=0x00;
P2M0=0xFF;
P2M1=0x00;
while(1)
{
on=0;
/*colorWipe(0xff0000,1); //红色
HAL_Delay(10000);
colorWipe(0xff00,1); //绿色
HAL_Delay(10000);
colorWipe(0xff,1);//蓝色
HAL_Delay(10000);
colorWipe(0xffff00,1); //黄色
HAL_Delay(10000);
colorWipe(0xffff,1); //青色
HAL_Delay(10000);
colorWipe(0xff00ff,1); //紫色
HAL_Delay(10000);
colorWipe(0xffffff,1); //白色
HAL_Delay(10000);
colorWipe(0x00,1); //off
HAL_Delay(10000);*/
Watercolor(0xff0000, 100);//红色
HAL_Delay(1000);
Watercolor(0xff00, 100);//绿色
HAL_Delay(1000);
Watercolor(0xff, 100);//蓝色
HAL_Delay(1000);
Watercolor(0xffff00, 100); //黄色
HAL_Delay(1000);
Watercolor(0xffff, 100);//青色
HAL_Delay(1000);
Watercolor(0xff00ff, 100); //紫色
HAL_Delay(1000);
Watercolor(0xffffff, 100); //白色
HAL_Delay(1000);
colorWipe(0x00,1); //off
HAL_Delay(10000);
/*colorWipe(0xff0000,100); //红色
HAL_Delay(1000);
colorWipe(0x00,100); //0ff
HAL_Delay(1000);
colorWipe(0xff00,100); //绿色
HAL_Delay(1000);
colorWipe(0x00,100); //0ff
HAL_Delay(1000);
colorWipe(0xff,100);//蓝色
HAL_Delay(1000);
colorWipe(0x00,100); //0ff
HAL_Delay(1000);
colorWipe(0xffff00,100); //黄色
HAL_Delay(1000);
colorWipe(0x00,100); //0ff
HAL_Delay(1000);
colorWipe(0xffff,100); //青色
HAL_Delay(1000);
colorWipe(0x00,100); //0ff
HAL_Delay(1000);
colorWipe(0xff00ff,100); //紫色
HAL_Delay(1000);
colorWipe(0x00,100); //0ff
HAL_Delay(1000);
colorWipe(0xffffff,100); //白色
HAL_Delay(1000);
colorWipe(0x00,100); //0ff
HAL_Delay(1000);*/
}
}
复制代码
作者:
hhdsdy
时间:
2021-11-10 13:09
2812不需要所有的灯珠一起更新,需要改变哪个就指定哪个进行改变,对于对开的,可以在中间灯珠先往下循环送数据,送完后再从中间往上送数据,完成一次点亮
作者:
名字不是重点
时间:
2021-11-10 15:25
就一个思路:36个灯就开108个字节的数组。把要显示的色值,填充到对应数组单元中,填满108个字节后,一次发出。
切记一点:发送过程要关总中断,发完再开总中断
,就不会被其它的中断打扰发送了。
至于点灯花样就看你如何去构思了。
作者:
wfqxgw
时间:
2021-11-10 16:23
没有其它办法的。只能全部一起更新。因为数据是单向串联传输的。你要把数据送到中间。必须先经过前面的LED中转。
作者:
己独
时间:
2021-11-10 18:10
void acc_mode555(void) //á½±ßíùÖD¼ä¶Ñ»y
{
u8 i,xx, yy;
flow_color0 = retColor(choose_color);
xx = WS2811_TOTAL_NODES1 - g_flow_temp - 1;
yy = WS2811_TOTAL_NODES1 - g_flow - 1;
EA = 0;
for(i = 0; i < WS2811_TOTAL_NODES1; i++)
{
if(g_flow == i || i > xx)ws28xxSend_24Bits(flow_color0);
else ws28xxSend_24Bits(flow_color1);
}
for(i = 0; i < WS2811_TOTAL_NODES1; i++)
{
if(yy == i || i < g_flow_temp)ws28xxSend_24Bits(flow_color0);
else ws28xxSend_24Bits(flow_color1);
}
EA = 1;
nrzSendResetCode();
g_flow++;
if(g_flow >= WS2811_TOTAL_NODES1 - g_flow_temp)
{
g_flow = 0;
g_flow_temp++;
if(g_flow_temp >= WS2811_TOTAL_NODES1)
{
g_flow_temp = 0;
flow_color1 = flow_color0;
choose_color++;
if(choose_color >= 7)
{
choose_color = 0;
}
}
}
}
作者:
名字不是重点
时间:
2021-11-10 21:36
hhdsdy 发表于 2021-11-10 13:09
2812不需要所有的灯珠一起更新,需要改变哪个就指定哪个进行改变,对于对开的,可以在中间灯珠先往下循环送 ...
你确定?除非你是一个灯一个IO才能做到。。
作者:
kxcuser
时间:
2021-11-11 08:47
感谢大家的回复
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1