|
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
#define led P2
sbit speaker=P1^4;//喇叭
sbit key1=P1^0; //放內(nèi)置音樂(lè)
sbit key2=P1^1; //放彈奏音樂(lè)
sbit key3=P1^2; //儲(chǔ)存清零
sbit Do=P3^0;
sbit Re=P3^1;
sbit Mi=P3^2;
sbit Fa=P3^3;
sbit So=P3^4;
sbit La=P3^5;
sbit Si=P3^6;
sbit Do_=P3^7; //八個(gè)音符按鍵
uchar a,b,num_yf,num_jp,jiepai;
uchar code yinfu[]={0xfb,0xe9, //Do
0xfc,0x5c, //Re
0xfc,0xc1, //Mi
0xfc,0xe5, //Fa
0xfd,0x45, //So
0xfd,0x92, //La
0xfd,0xd1, //Si
0xfd,0xee, //Do#
0x00,0x00,}; //間隔
uchar code led_on[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe,0xff};
uchar code shengri_tone[]={ 1,9,1,2,1,4,3,9, //生日快樂(lè)音調(diào)
1,9,1,2,1,5,4,9,
1,9,1,8,6,4,3,2,9,
7,9,7,6,4,5,4,9 }; //9代表不發(fā)聲,即停頓;數(shù)字即為音調(diào)
uchar code shengri_beat[]={ 24,1,24,48,48,48,72,5, //節(jié)拍
24,1,24,48,48,48,72,5,
24,1,24,48,48,48,48,72,5,
24,1,24,48,48,48,72,5 }; //節(jié)拍,即tone表各音調(diào)的延時(shí)
uchar xdata save[220]; //保存音符的數(shù)組
uchar idata save_beat[220]; //保存節(jié)拍的數(shù)組
void check_key();//改為P3組為按鍵
void delay(uint z);//延時(shí)函數(shù)聲明
void delay1(void);//聲明第二個(gè)延時(shí)函數(shù)
void play1(void);//播放生日快樂(lè)
void play2(void);//播放存儲(chǔ)存儲(chǔ)的音樂(lè)
void cunchu()
{
jiepai++;
if(save[num_yf]==9)
delay(20);
else
delay(15);
if(jiepai>=251)
jiepai=250;
}
void main() //主函數(shù)
{ led=0x5a;
speaker=1;
TMOD=0x01;
TH0=a;
TL0=b; //定時(shí)器工作方式1
ET0=1; //中斷允許
TR0=1; //打開(kāi)定時(shí)器
//進(jìn)入循環(huán)
while(1)
{
check_key(); //掃描按鍵
}
}
void time0() interrupt 1 //定時(shí)器0工作函數(shù)
{
TH0=a;
TL0=b; //初值
speaker=~speaker; //喇叭取反,喇叭高低電平變換才能發(fā)生
}
void check_key() //按鍵函數(shù)
{
uint i;
if(key1==0) //播放內(nèi)置音樂(lè)按鍵
{
delay(10); //延時(shí)去抖
while(key1==0); //再次判斷
play1(); //播放內(nèi)置音樂(lè)
}
if(key2==0) //播放彈奏的音樂(lè)按鍵
{
delay(10); //延時(shí)去抖
while(key2==0); //再次判斷按鍵是否按下
play2(); //播放彈奏的音樂(lè)
}
if(key3==0) //清除彈奏的按鍵
{
delay(10);
while(key3==0);
for(i=0;i<220;i++) //將保存數(shù)據(jù)的數(shù)組清零
{
save[i]=0; //清零音符
save_beat[i]=0; //清零節(jié)拍
num_yf=0;
num_jp=0; //計(jì)數(shù)變量清零
}
}
if(P3!=0xff) //彈奏按鍵按下
{
if(Do==0) //第一個(gè)按鍵按下
{
a=0xfb;b=0xe9;EA=1;save[num_yf]=1;led=0x7f; //ab賦值,保存音符到對(duì)應(yīng)的位置
}
else if(Re==0) //同上
{
a=0xfc;b=0x5c;EA=1;save[num_yf]=2;led=0xbf;
}
else if(Mi==0)
{
a=0xfc;b=0xc1;EA=1;save[num_yf]=3;led=0xdf;
}
else if(Fa==0)
{
a=0xfc;b=0xef;EA=1;save[num_yf]=4;led=0xef;
}
else if(So==0)
{
a=0xfd;b=0x45;EA=1;save[num_yf]=5;led=0xf7;
}
else if(La==0)
{
a=0xfd;b=0x92;EA=1;save[num_yf]=6;led=0xfb;
}
else if(Si==0)
{
a=0xfd;b=0xd0;EA=1;save[num_yf]=7;led=0xfd;
}
else if(Do_==0)
{
a=0xfd;b=0xee;EA=1;save[num_yf]=8;led=0xfe;
}
while(!Do||!Re||!Mi||!Fa||!So||!La||!Si||!Do_)//按鍵釋放,按鍵都松開(kāi)跳出
{cunchu();} //如果按鍵一直按下,調(diào)用存儲(chǔ)函數(shù),記錄按鍵按下的時(shí)長(zhǎng),也就是節(jié)拍
save_beat[num_jp]=jiepai; //按鍵松開(kāi)后,將節(jié)拍數(shù)據(jù)保存到數(shù)組
jiepai=0; //變量清零,等待下次按鍵按下
EA=0; //關(guān)閉中斷
speaker=1;
led=0xff; //關(guān)閉喇叭
num_jp++;
num_yf++; //音符和節(jié)拍計(jì)數(shù)加
if(num_jp>=220||num_yf>=220) //最大計(jì)數(shù)219個(gè)
{
num_jp=219;
num_yf=219;
}
while(P3==0xff&&key1==1&&key2==1&&key3==1)//按鍵都不按下時(shí)
{
a=0x00;b=0x00; //初值清零
save[num_yf]=9; //保存空音符到數(shù)組
cunchu(); //調(diào)用存儲(chǔ)函數(shù)
}
save_beat[num_jp]=jiepai; //保存節(jié)拍數(shù)據(jù)到數(shù)組
jiepai=0; //節(jié)拍清零
EA=0; //關(guān)閉中斷
speaker=1;
led=0xff; //關(guān)閉喇叭
num_jp++;
num_yf++; //變量加
if(num_jp>=220||num_yf>=220) //最大加到219
{
num_jp=219;
num_yf=219;
}
}
}
void delay(uint z) //延時(shí)函數(shù),大約延時(shí)1ms,不精確
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void delay1(void)//第二個(gè)延時(shí)函數(shù)
{
uchar n=15;
while(n--)
{
uchar i;
for(i=0;i<125;i++);
}
}
void play1(void)//播放內(nèi)置音樂(lè)
{
uchar m=0;
uchar s;
uchar c;
uchar d;
while(1)
{
EA=0;
d=shengri_tone[m];
c=shengri_tone[m]; //取音符
s=shengri_beat[m];
led=led_on[d-1];
a=yinfu[2*c-2];
b=yinfu[2*c-1];
EA=1;
while(s--)
{
delay1();
}
led=0xff;
m++;
if(m>=33) //數(shù)值是shengri相關(guān)表中的元素?cái)?shù)量
{
a=0;
b=0;
EA=0;
return;
} //數(shù)值是shengri相關(guān)表中的元素?cái)?shù)量
}
}
void play2(void)//播放被存儲(chǔ)的音樂(lè)
{
uchar m=0;
uchar s;
uchar c;
uchar d;
while(1)
{
EA=0;
c=save[m];
d=c; //取音符
s=save_beat[m]; //取節(jié)拍
a=yinfu[2*c-2];
b=yinfu[2*c-1];
led=led_on[d-1];
if(a!=0x00)
{
EA=1;
}
while(s--)
{
delay1();
}
led=0xff;
m++;
if(m>=num_yf)
{
a=0;
b=0;
EA=0;
led=0xff;
return;
}
}
}
|
|