WS2812面板灯制作教程!
视频效果展示:
功能描述 电脑上,使用MADRIX 2.0 软件,读取声卡数据并转换成频谱图像,通过USB口发送给MADRIX板子,转换成DMX512协议,送入面板灯。再由STC8单片机解码,发送给WS2812灯珠,显示出和电脑上一模一样的图像。 同类方案广泛应用于超大型酒吧、室外广场装饰灯等。 所需材料: 1、MADRIX软件(学习可以使用免费版本,如需正规使用请联系官方购买) 2、MADRIX控制器,输出电脑信号转换成DMX512信号即可 3、STC单片机,1KB的RAM,1KB的ROM,最好是带两个串口,宽电压的稳定。 4、MAX490芯片,用于将DMX512协议的485差分信号转换成TTL信号 5、WS2812灯珠 6、电源,输出电压恒压5V,输出电流根据灯珠数量选择。 关于制作: 1、原理图请参考《WS2812面板灯原理图》 2、PCB根据自己需要,选择灯珠的布局形式。标准的DMX512协议最多支持170颗RGB彩灯的灰度数据。 3、STC单片机的程序,请参考《DMX512转WS2812 面板灯程序》 4、WS2812灯珠调试,请参考《全真彩WS2812芯片LED介绍》 关于MADRIX软件的版权 1、软件的下载:见附件 2、软件的授权:学习或者测试,可以直接下载上面的MADRIX软件安装使用。公司使用请务必到MADRIX官网购买正版授权证明。如贵公司侵权使用,所产生法律责任与本文无关!软件在为授权的情况下,只能用于调试,并且会按一定时间自动黑屏!不能用于工业项目的客户使用! 3、安装软件后需要安装驱动才能正常使用MADRIX解码板 4、我们的MADRIX板,只支持MADRIX 2.0版本,升级后将不能正常使用! MADRIX软件的简单使用 1、打开软件,按F4,搜索MADRIX设备出现下列OUT设备,就表示找到设备! 2、再按F2,设置面板灯的布局方式,下图是我们的13*13像素点的面板灯的设置 3、选择花样 S2LEQUAlizer就是频谱显示,可以调节声音显示幅度、灯珠亮度、显示速度等参数
电路原理图如下:
级联169颗灯珠,排列成13*13矩阵,总电流7A
适当距离需要增加0.1uF电容作为电源滤波,推荐50颗电容分开放
单颗灯珠电流40毫安,单颗灯珠功耗0.2瓦
单片机源程序如下(主程序):
- //***********************************************************************************
- //1、程序适用时钟为24M
- //2、DMX512的串口2,每48微秒进入一次中断,中断服务里使定时器0重新计时。
- //3、接收完513字节后,超过1000微秒保持高电平不进串口中断,定时器溢出使status_flag翻转一次。
- //4、如果status_flag是1,那么接下来的DMX512丢弃不用!把DMX接收的数据拷贝并发送给WS2812。
- //5、发送完WS2812数据后,再次允许串口2中断,status_flag再翻转一次,保持DMX512数据。
- //6、核心目的是留一帧丢一帧,保证DMX512解码和WS2812发送,在时间上错开。
- //***********************************************************************************
- #include "all.h"
- bit status_flag=1;
- void Timer0_Init(void) //1000微秒 24M时钟
- {
- AUXR &= 0x7F; //定时器工作在12T模式
- TMOD &= 0xF0; //设置为定时器模式
- TMOD |= 0x01; //设置为定时器模式
- TL0 = 0x30; //定时器初值
- TH0 = 0xF8; //定时器初值
- TF0 = 0; //清除TF0标志
- TR0 = 1; //启动定时0
- ET0=1; //允许定时器中断
- }
- void Timer0_Routnie (void) interrupt 1 using 1
- {
- static u8 WS2812_Write_Buffer_old; //无信号等待用
- static u16 count; //无信号等待用
- u16 i;
-
- status_flag=~status_flag; //帧标志位,一次DMX取反一次
- if(status_flag==1) //如果是奇数,下次DMX512丢弃,而发送WS2812数据
- {
- WS2812_DAT=0; //先发送低电平复位时间
- IE2&=0xfe; //关闭DMX的串口2中断
- for(i=1;i<Pixel_Data_Num;i++)
- {
- WS2812_Write_Buffer[i]=DMX512_Read_Buffer[i];//DMX数据复制给WS2812
- }
- if(WS2812_Write_Buffer_old!=WS2812_Write_Buffer[1])//如果数据改变
- {
- count=0; //计数从0开始
- WS2812_Write_Buffer_old=WS2812_Write_Buffer[1];//刷新数据。
- }
- else //如果数据不改变
- {
- count++; //计时
- if(count>2417) //如果长时间数据不改变
- {
- for(i=1;i<Pixel_Data_Num;i++)
- {
- WS2812_Write_Buffer[i]=0; //说明通信故障,自动黑屏
- DMX512_Read_Buffer[i]=0; //说明通信故障,自动黑屏
- }
- }
- }
- WS2812_Display_Ser(); //传输数据到WS2812
- IE2|=0x01; //串口2中断再次允许,下次保存DMX512,不发送WS2812数据
- }
- }
- void main()
- {
- u16 i;
- for(i=0;i<Pixel_Data_Num;i++)
- {
- WS2812_Write_Buffer[i]=0; //开机先黑屏
- DMX512_Read_Buffer[i]=0; //开机先黑屏
- }
- DMX_Init();
- P1M0=0;P3M0=0;
- P1M1=0;P3M1=0;
- WS2812_Init();
- Timer0_Init();
- EA=1;
- while(1);
- }
复制代码
DMX512_Drive.c
- #include "all.h"
- u8 xdata DMX512_Read_Buffer[Pixel_Data_Num];
- //**********************************************
- // DMX512初始化串口与定时器 24M
- //**********************************************
- void DMX_Init()
- {
- S2CON = 0xD0; //9位数据,波特率可设置
- AUXR &= 0xFB; //定时器2工作在12T模式
- T2L = 0xFE; //定时器2初值
- T2H = 0xFF; //定时器2初值
- AUXR |= 0x10; //启动定时器2
- IE2|=0x01; //串口2中断允许
- }
- //**********************************************
- // 串口2的中断服务函数 S2RI=1才能进入中断服务
- //**********************************************
- void Uart2_Routnie (void) interrupt 8 //using 1
- {
- static u16 data DMX_count;
- TL0 = 0x30; //定时器0重装初值,防止定时器0中断发生
- TH0 = 0xF8; //定时器0重装初值,防止定时器0中断发生
- switch(S2CON&0x05) //判断S2RB8以及S2RI
- {
- case 1:DMX_count=0;S2CON&=0xf0;break; //如果S2RB8是0,S2RI是1,清除S2RI
- case 5: //如果S2RB8是1,S2RI是1
- {
- if(DMX_count<Pixel_Data_Num) //只保存需要的最多字节数量
- {
- DMX512_Read_Buffer[DMX_count]=S2BUF;//保存
- }
- DMX_count++; //计数器增加
- }
- S2CON&=0xf0; //清除S2RI
- break;
- }
- }
复制代码
WS2812_Drive.c
- #include "all.h"
- u8 xdata WS2812_Write_Buffer[Pixel_Data_Num];
- //**********************************************
- // WS2812初始化
- //**********************************************
- void WS2812_Init()
- {
- WS2812_DAT=1; //拉高
- }
- //**********************************************
- // WS2812 发送数据 0.5625us是高电平的界限。发0高电平不能超过0.5625
- //**********************************************
- void WS2812_Write_Data(u8 *Point,u8 len)
- {
- u8 data i,j,k,Value;
- for(i=0;i<len;i++) //多少个RGB灯就发送多少次
- {
- for(j=0;j<3;j++) //每个灯是R G B 三种颜色数据
- {
- switch(j) //红绿调换位置。
- {
- case 0:Value=*(Point+1);break;
- case 1:Value=*(Point);break;
- case 2:Value=*(Point+2);break;
- }
- for(k=0;k<8;k++) //每个数据是8位
- {
- WS2812_DAT=1;
- if(Value&0x80) //判断数据是不是1
- {
- _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
- _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
- WS2812_DAT=0; //0.35us
- //_nop_();_nop_();
- }
- else
- {
- WS2812_DAT=0; //1.36us
- _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
- _nop_();_nop_();_nop_();_nop_();_nop_();
-
-
- }
- Value<<=1;
- }
- }
- Point+=3;//指针加加
- }
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
WS2812面板灯制作资料.zip
(7.71 MB, 下载次数: 288)
|