原程序如下
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit duan=P2^6;
sbit key1=P3^2;//按key1可切换花样
sbit key2=P3^3;//按key2可切换歌曲
sbit fm=P3^7;//蜂鸣器连续的IO口
sbit P34=P3^4;//矩阵键盘的一列
uchar code huayang1[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe,
0xfd,0xfb,0xf7,0xef,0xdf,0xbf};//花样1
uchar code huayang2[]={0x7f,0xfe,0xbf,0xfd,0xdf,0xfb,0xef,0xf7,
0xef,0xfb,0xdf,0xfd,0xbf,0xfe};//花样2
uchar code huayang3[]={0x7f,0x3f,0x1f,0x0f,0x07,0x03,0x01,0x0,
0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff};
char code huayang4[]={ 0x55,0xaa,0xcc,0x33,0x99,0x66,0x0f,0xf0};
uchar count1;//花样标志
uchar count2;//歌曲标志
uchar timeh,timel,i;
//================简谱====================
//编程规则:字节高位是简谱,低位是持续时间,
//代表多少个十六分音符
//1-7代表中央C调,8-E代表高八度,0代表停顿
//最后的0是结束标志
uchar code lzlh[]={ //两只老虎
0x14,0x14,0x24,0x34,0x14,0x14,0x24,0x34,0x14,
0x34,0x44,0x58,0x34,0x44,0x58,
0x53,0x61,0x53,0x41,0x34,0x14,
0x53,0x61,0x53,0x41,0x34,0x14,
0x14,0x54,0x18,
0x14,0x54,0x18,
0xFF //歌曲结束标志
};
uchar code sb[]={ //送别
0x54,0x54,0x32,0x52,0x88,0x64,0x84,0x58,
0x54,0x12,0x22,0x34,0x22,0x12,0x28,0x04,0x04,
0x54,0x32,0x52,0x86,0x72,0x64,0x84,0x58,
0x54,0x22,0x32,0x46,0xB2,0x18,0x04,0x04,
0x64,0x84,0x88,0x74,0x62,0x72,0x88,
0x62,0x72,0x82,0x62,0x62,0x52,0x32,0x12,0x28,0x04,0x04,
0x54,0x32,0x52,0x86,0x72,0x64,0x84,0x58,
0x54,0x22,0x32,0x46,0xB2,0x18,0x04,0x04,
0xFF
};
uchar code mlh[]={ //茉莉花
0x31,0x21,0x31,0x51,0x61,0x51,0x81,0x61,
0x51,0x31,0x54,0x62,0x82,0x91,0x81,0x58,
0x51,0x31,0x54,0x62,0x82,0x91,0xA1,0x91,
0x61,0x52,0x52,0x22,0x31,0x51,0x31,0x21,0x11,0xD1,0x16,
0x31,0x21,0x12,0x23,0x31,0x52,0x61,0x81,
0x62,0x52,0x51,0x31,0x22,
0x31,0x51,0x31,0x21,0x11,0x21,0xD4,0x12,
0x23,0x31,0x11,0xD1,0x11,0xD1,0xC6,
0x31,0x21,0x12,0x23,0x31,0x52,0x61,0x81,
0x62,0x52,0x51,0x31,0x22,
0x31,0x51,0x31,0x21,0x11,0x21,0xD4,0x12,
0x23,0x31,0x11,0xD1,0x11,0xD1,0xC6,
0xFF
};
uchar code xxx[]={ //小星星
0x12,0x12,0x52,0x52,0x62,0x62,0x54,0x42,
0x42,0x32,0x32,0x22,0x21,0x14,
0x52,0x52,0x42,0x42,0x32,0x32,0x24,0x52,
0x52,0x42,0x42,0x32,0x32,0x24,
0x12,0x12,0x52,0x52,0x62,0x62,0x64,0x42,
0x32,0x32,0x22,0x22,0x14,
0xFF
};
//==============简谱音调对应的定时器初值=======
//适合11.0592M的晶振
uchar code cuzhi[]={
0xff,0xff,//占位
0xFC,0x8E,//中央C调1-7
0xFC,0xED,
0xFD,0x43,
0xFD,0x6A,
0xFD,0xB3,
0xFD,0xF3,
0xFE,0x2D,
0xFE,0x47, //高八度1-7
0xFE,0x76,
0xFE,0xA1,
0xFE,0xC7,
0xFE,0xD9,
0xFE,0xF9,
0xFF,0x16
};
uchar yinyue[]={0xff,0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0x0,0x0};
//将音调转化为对应的LED样式
void delay1(uint z); //延时1MS
void delay(uint z); //延时165MS,即十六分音符
void song();
main()
{ uchar x;
count1=0;//流水灯无花样
count2=1;//唱第一首歌
P34=0;//选取矩阵键盘的一列
EA=1;//开总中断
EX0=1;//开外部中断0
IT0=1;//外部中断0下降沿触发方式
EX1=1;//开外部中断1
IT1=1;//外部中断1下降沿触发方式
TMOD=0x01;//定时器0工作在方式1
TH0=0;
TL0=0;
ET0=1;
while(1)
{
if(count1!=0)
{
switch(count1)
{
case 1:
for(x=0;x<14;x++)
{
duan=1;
P2=huayang1[x];
fm=1;
delay1(300);
duan=0;
if(count1!=1)
break;
}
break;
case 2:
for(x=0;x<14;x++)
{
duan=1;
P2=huayang2[x];
fm=1;
delay1(300);
duan=0;
if(count1!=2)
break;
}
break;
case 3:
for(x=0;x<16;x++)
{
duan=1;
P2=huayang3[x];
fm=1;
delay1(300);
duan=0;
if(count1!=3)
break;
}
break;
case 4:
for(x=0;x<8;x++)
{
duan=1;
P2=huayang4[x];
fm=1;
delay1(300);
duan=0;
if(count1!=4)
break;
}
break;
}
}
else
{
song();
delay1(1000);
}
}
}
void int0() interrupt 0
{
EA=0;//关总中断
delay1(1);//去抖
if(key1==0)
{
count2=0;//不让蜂鸣器唱歌
TR0=0;
count1++;
if(count1==5)
count1=1;
}
EA=1;//开总中断
}
void int1() interrupt 2
{
EA=0;//关总中断
delay1(1);//去抖
if(key2==0)
{
count1=0;//流水灯无花样
TR0=1;
i=0;//从头开始唱
count2++;
if(count2==3)
count2=1;
}
EA=1;//开总中断
}
void timer0() interrupt 1 //用于产生各种音调
{
TH0=timeh;
TL0=timel;
fm=~fm;
}
void song()
{
uint temp;
uchar jp;//jp是简谱
i=0;
while(1)
{ if(count2==0)
{
break;
}
if(count2==1) //选曲
temp=lzlh[i];
if(count2==2)
temp=sb[i];
if(count2==2)
temp=mlh[i];
if(count2==3)
temp=xxx[i];
if(temp==0xff)
break;
jp=temp/16; //取数的高4位
duan=1;
P2=yinyue[jp];
duan=0;
if(jp!=0)
{
timeh=cuzhi[jp*2];
timel=cuzhi[jp*2+1];
}
else
{
TR0=0;
fm=1;//关蜂鸣器
}
delay(temp%16); //取数的低4位
TR0=0; //唱完一个音停10MS
fm=1;
delay1(10);
TR0=1;
i++;
}
TR0=0;
fm=1;
}
void delay(uint z) //延时165MS,即十六分音符
{ uint x,y;
for(x=z;x>0;x--)
for(y=19000;y>0;y--);
}
void delay1(uint z) //延时1MS
{ uint x,y;
for(x=z;x>0;x--)
for(y=112;y>0;y--);
}
|