標題:
用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環(huán)形時鐘的硬件符合條件,板上60顆燈珠,stc主控,帶usb轉串口,那么我們就用這個stc來做流光溢彩吧。
查了一下網(wǎng)上也沒有stc的教程,就自己分析了一下運行過程。
首先由PC機運行AmbiBox軟件抓取屏幕點,取得rgb顏色數(shù)據(jù)。
然后由串口發(fā)送至單片機解析。
解析后的數(shù)據(jù)刷新至rgbled顯示。
過程貌似比較簡單,但我們得分析其中的協(xié)議。
網(wǎng)查資料得到 Ada模式協(xié)議如下:
前三個字節(jié)分別是Ada,然后3個字節(jié)的前2個是led個數(shù),最后一個是校驗碼,接著就是對應個數(shù)的rgb數(shù)據(jù),每個led3字節(jié),分別對應r,g,b。
有了這個就簡單了。構建程序流程如下
單片機主頻33.1776(為了配合串口波特率)
啟動程序->初始化串口(定時器2,波特率115200,)->初始化led數(shù)組 ->檢測顯示(紅,綠,藍各顯示一遍)->開啟串口接收中斷->主循環(huán)判斷如果不允許中斷則刷新rgbled,刷新完成后開啟中斷,如果允許中斷則等待不允許中斷。
中斷函數(shù)中流程->依次判斷接收字符是否對應,如果前3個字節(jié)對應則 接收電燈數(shù)據(jù),并將數(shù)據(jù)保存至數(shù)組中,接收一組數(shù)據(jù)完畢,失能中斷,這樣不會因中斷接收數(shù)據(jù)影響刷新。
圖我也懶得拍照了,程序上傳上來,大家想做的可以自己畫個板子,燒上代碼就行了,至于AmbiBox自行某度即可。
單片機源程序如下:
#include "stc15.h"
#include "ws2812.h"
uchar xdata rgb[60][3];//led數(shù)組
uchar sendrgb=0;//預發(fā)送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位數(shù)據(jù),可變波特率
AUXR |= 0x01; //串口1選擇定時器2為波特率發(fā)生器
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(初始化數(shù)組)
{
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輸出函數(shù)
{
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; //開啟中斷,可接收數(shù)據(jù)
while(1)
{
if(EA==0)//當中斷關閉,表示一幀數(shù)據(jù)接收完畢
{
display();//將當前數(shù)據(jù)刷新
EA=1;//開啟中斷,接收下一幀數(shù)據(jù)
}
}
}
void Uart() interrupt 4 //串口中斷
{
uchar dat=0;
if (RI)
{
dat=SBUF;
RI = 0; //清除RI位
if(dat==0x41&&in==0)
{
in=1; //判斷數(shù)據(jù)0位(A)
SBUF=in;
return;
}
if(dat==0x64&&in==1) //判斷數(shù)據(jù)1位(d)
{
in=2;
SBUF=in;
return;
}
else if(dat==0x61&&in==2) //判斷數(shù)據(jù)2位(a)
{
in=3;
SBUF=in;
return;
}
else if(in==3) //讀取高位LED個數(shù)
{
h=dat;
in++;
return;
}
else if(in==4) //讀取低位LED個數(shù)
{
l=dat;
in++;
return;
}
else if(in==5) //讀取校驗值
{
o=dat;
if(o!=(h^l^0x55)) in=0; //校驗
else in++;
return;
}
else if(in>=6) //進入數(shù)據(jù)讀取階段
{
rgb[(in-6)/3][(in-6)%3]=dat;//將數(shù)據(jù)寫入數(shù)組
if((in-6)/3==l) //根據(jù)發(fā)來的led個數(shù)確定數(shù)據(jù)是否接收完畢
{
in=0;
EA=0;
return;
}
else in++;
return;
}
else //如果in小于6,且中途數(shù)據(jù)中斷。則重新開始。
{
in=0;
return;
}
}
}
復制代碼
所有資料51hei提供下載:
流光溢彩.rar
(35.49 KB, 下載次數(shù): 38)
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;.......直接實現(xiàn)用EA=1/0來實現(xiàn)總中斷?
作者:
ddwy43
時間:
2021-10-12 00:48
用89C52單片機燒上代碼,P1.0接燈帶數(shù)據(jù)端,不亮。
是89C52芯片不行,要stc15芯片? 還是要改代碼的哪里?
換過Keil軟件的器件為89C52,頭文件試過stc15w.h和reg52.h。
不太懂望指教。
arduino點亮過
作者:
ddwy43
時間:
2021-10-12 01:00
本帖最后由 ddwy43 于 2021-10-12 01:03 編輯
arduino的點亮過,燈帶也就正常了
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1