标题:
用stc单片机制作PC流光溢彩 源程序
[打印本页]
作者:
lovexulu
时间:
2020-10-19 20:13
标题:
用stc单片机制作PC流光溢彩 源程序
近日在B站看到许多PC流光溢彩效果,如:
https://www.bilibili.com/video/BV1fJ411B7bp?from=search&seid=16736407731500993634
还有
https://www.bilibili.com/video/BV1MC4y1h7iB?from=search&seid=16736407731500993634
效果是真不错,还有许多制作的视频帖子,但是。。。。。。都是基于arduino制作的,我手头上只有一块自制的arduino uno,个头有点大,洞洞板上还没有usb转串口,有点麻烦。正好上次制作rgb环形时钟的硬件符合条件,板上60颗灯珠,stc主控,带usb转串口,那么我们就用这个stc来做流光溢彩吧。
查了一下网上也没有stc的教程,就自己分析了一下运行过程。
首先由PC机运行AmbiBox软件抓取屏幕点,取得rgb颜色数据。
然后由串口发送至单片机解析。
解析后的数据刷新至rgbled显示。
过程貌似比较简单,但我们得分析其中的协议。
网查资料得到 Ada模式协议如下:
前三个字节分别是Ada,然后3个字节的前2个是led个数,最后一个是校验码,接着就是对应个数的rgb数据,每个led3字节,分别对应r,g,b。
有了这个就简单了。构建程序流程如下
单片机主频33.1776(为了配合串口波特率)
启动程序->初始化串口(定时器2,波特率115200,)->初始化led数组 ->检测显示(红,绿,蓝各显示一遍)->开启串口接收中断->主循环判断如果不允许中断则刷新rgbled,刷新完成后开启中断,如果允许中断则等待不允许中断。
中断函数中流程->依次判断接收字符是否对应,如果前3个字节对应则 接收电灯数据,并将数据保存至数组中,接收一组数据完毕,失能中断,这样不会因中断接收数据影响刷新。
图我也懒得拍照了,程序上传上来,大家想做的可以自己画个板子,烧上代码就行了,至于AmbiBox自行某度即可。
单片机源程序如下:
#include "stc15.h"
#include "ws2812.h"
uchar xdata rgb[60][3];//led数组
uchar sendrgb=0;//预发送rgb变量
uchar h=0,l=0,o=0;
uchar in=0;
void delayms(int x)
{
int i,j;
for(i=0;i<x;i++)
for(j=0;j<1000;j++);
}
void UartInit(void) //115200bps@33.1776MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR |= 0x04; //定时器2时钟为Fosc,即1T
T2L = 0xB8; //设定定时初值
T2H = 0xFF; //设定定时初值
AUXR |= 0x10; //启动定时器2
ES = 1; //使能串口1中断
}
void initrgb(uchar st,uchar sp,uchar rg0,uchar rg1,uchar rg2)//起始位,结束位,rgb1,2,3(初始化数组)
{
uchar i,j;
for(i=st;i<sp;i++)
{
for(j=0;j<3;j++)
{
switch(j)
{
case 0:
rgb[i][j]=rg0;
break;
case 1:
rgb[i][j]=rg1;
break;
case 2:
rgb[i][j]=rg2;
break;
}
}
}
}
void display() //刷新rebled输出函数
{
uchar i,j,k;
for(i=0;i<60;i++)
{
for(j=0;j<3;j++)
{
sendrgb=rgb[i][j];
for(k=0;k<8;k++)
{
if(sendrgb&0x80)
st1();
else
st0();
sendrgb<<=1;
}
}
}
stop();
}
void main()
{
UartInit();//初始化串口
initrgb(0,60,50,0,0); //测试绿
display();
delayms(1000);
initrgb(0,60,0,50,0); //测试红
display();
delayms(1000);
initrgb(0,60,0,0,50); //测试蓝
display();
delayms(1000);
initrgb(0,60,0,0,0); //清屏
display();
delayms(1000);
EA = 1; //开启中断,可接收数据
while(1)
{
if(EA==0)//当中断关闭,表示一帧数据接收完毕
{
display();//将当前数据刷新
EA=1;//开启中断,接收下一帧数据
}
}
}
void Uart() interrupt 4 //串口中断
{
uchar dat=0;
if (RI)
{
dat=SBUF;
RI = 0; //清除RI位
if(dat==0x41&&in==0)
{
in=1; //判断数据0位(A)
SBUF=in;
return;
}
if(dat==0x64&&in==1) //判断数据1位(d)
{
in=2;
SBUF=in;
return;
}
else if(dat==0x61&&in==2) //判断数据2位(a)
{
in=3;
SBUF=in;
return;
}
else if(in==3) //读取高位LED个数
{
h=dat;
in++;
return;
}
else if(in==4) //读取低位LED个数
{
l=dat;
in++;
return;
}
else if(in==5) //读取校验值
{
o=dat;
if(o!=(h^l^0x55)) in=0; //校验
else in++;
return;
}
else if(in>=6) //进入数据读取阶段
{
rgb[(in-6)/3][(in-6)%3]=dat;//将数据写入数组
if((in-6)/3==l) //根据发来的led个数确定数据是否接收完毕
{
in=0;
EA=0;
return;
}
else in++;
return;
}
else //如果in小于6,且中途数据中断。则重新开始。
{
in=0;
return;
}
}
}
复制代码
所有资料51hei提供下载:
流光溢彩.rar
(35.49 KB, 下载次数: 36)
2020-10-19 20:13 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
lovexulu
时间:
2020-10-19 20:21
如果大家都想做一个玩玩,我就再出个详细的教程帖子。画好电路图,PCB。
作者:
1746722427
时间:
2021-4-12 10:52
不错啊,坐等详细教程
作者:
木示
时间:
2021-4-19 11:38
新手请教,程序中好像没有把中断的程序写出来?IN0=0;EA=1;.......直接实现用EA=1/0来实现总中断?
作者:
ddwy43
时间:
2021-10-12 00:48
用89C52单片机烧上代码,P1.0接灯带数据端,不亮。
是89C52芯片不行,要stc15芯片? 还是要改代码的哪里?
换过Keil软件的器件为89C52,头文件试过stc15w.h和reg52.h。
不太懂望指教。
arduino点亮过
作者:
ddwy43
时间:
2021-10-12 01:00
本帖最后由 ddwy43 于 2021-10-12 01:03 编辑
arduino的点亮过,灯带也就正常了
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1