|
看到很多做心形燈的例子,自己也想著做一個,但是覺得僅有彩燈,不太完美,于是想加上音樂播放的程序。這次做了一個STC89C52的P0,P1,P2口控制24顆彩燈,P3^7口控制蜂鳴器發出音樂的例子。在仿真程序里面可以實現,但是移植到硬件上程序會跑飛,貼出來給大家看看,網上說中斷容易讓程序跑飛,這次STC89C52的T0,T1,INT0,INT1都使用了。其中T0是一個10ms中斷用于音樂基準,T1是一個50ms中斷,通過改變numtop的值,可以改變花樣燈額、的切換速度,INT0控制播放哪首曲子,INT1用于改變numtop的值,改變此數值就可以改變花樣燈的切換速度。
/*12Mhz晶振*/
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit key2=P3^3;//key2外部中斷1 控制花樣燈的切換速度
sbit key1=P3^2;//key1外部中斷0 控制播放哪首曲子
sbit voice=P3^7;//蜂鳴器定義
uchar code sound[]={0xff, //每個音階 不同拍子的數據 限于篇幅,完整數據請下載壓縮包
0x60,0x10,0x55,0x10,0x4c,0x10,0x48,0x10,0x40,0x10,0x39,0x10,0x33,0x10,
0x30,0x10,0x2b,0x10,0x26,0x10,0x24,0x10,0x20,0x10,0x1c,0x10,0x19,0x10,
0x18,0x10,0x15,0x10,0x13,0x10,0x12,0x10,0x10,0x10,0x0e,0x10,0x0d,0x10,//1/4拍子低音1到高音7
0x00};
uchar code kanong[]={0xff, //卡農 限于篇幅,完整數據請下載壓縮包
0x13,0x20,0x15,0x20,0x18,0x20,0x19,0x20,0x1c,0x20,0x20,0x20,0x1c,0x20,0x19,0x20,//第一行
0x18,0x20,0x19,0x20,0x1c,0x20,0x20,0x20,0x24,0x20,0x26,0x20,0x24,0x20,0x2b,0x20,//第二行
0x00};
code unsigned long Pattern[]={ //24顆LED燈花樣數據 限于篇幅,完整數據請下載壓縮包
0x00000000,0x00ffffff,0x00000000,0x00ffffff,//全亮全滅
};
uchar zdjs=0,jp,i=0;
uchar num=0,numtop=5,count=0;
void del(yj);
void delay(uint z);
void play(void)
{
uint dpjs=0;
uchar yj;
while(1)
{
zdjs=0;
if(count==0)
{
TR0=0;
break;
}
if(count==1) //選曲
{
dpjs++; yj=sound[dpjs]; //取出音階的頻率
dpjs++; jp=sound[dpjs]; //取出延時時長
}
if(count==2)
{
dpjs++; yj=kanong[dpjs];
dpjs++; jp=kanong[dpjs];
jp=jp*4; //這句是調音的
}
while(zdjs!=(jp))
{
if(yj!=0xff)
{
if(yj!=0) //判斷音樂是否播放完畢
{
voice=!voice;
del(yj);
}
else
{
dpjs=0;
break;
}
}
else
{
voice=0;
del(jp);
}
}
}
}
void Time0() interrupt 1 using 1 //產生音樂基準
{
TH0=0xd8, TL0=0xf0;
zdjs++;
}
void Time1() interrupt 3 //控制花樣燈的切換
{
TH1=0x3C, TL1=0xB0;
num++;
if(num==numtop)
{
num=0;
P0=Pattern[i];
P1=Pattern[i]>>8;
P2=Pattern[i]>>16;
i++;
if(i==135) i=0;
}
}
void int0() interrupt 0 //key1外部中斷0 控制播放哪首曲子
{
del(5);
EA=0;
if(key1==0)
{
count++; //count決定播放哪一首曲子
while(!key1);
if(count==4) count=0;
}
EA=1;
}
void int1() interrupt 2 //key2外部中斷1 控制花樣燈的切換速度
{
del(5); //去抖
EA=0; //關總中斷
numtop++;
// while(!key2); //去抖動
if(numtop==10) numtop=0; //numtop 代表最長延時時間
EA=1; //開總中斷
}
void del(yj) //簡單延時函數
{
uchar yj2=2;
while(yj!=0)
{
while(yj2!=0)
{
yj2--;
}
yj2=2;
yj--;
}
}
void main()
{
TMOD=0x11,IE=0x8a;
TH0=0xd8, TL0=0xf0; //10ms音樂基準
TH1=0x3C, TL1=0xB0; //50MS
EX0=1;//開外部中斷0
IT0=0;//外部中斷0下降沿觸發方式
EX1=1;//開外部中斷1
IT1=0;//外部中斷1下降沿觸發方式
TR0=1; TR1=1;
play();
}
仿真可行,但是硬件上會跑飛!!!!
哪位功夫深厚,能夠將她完善??
|
|