- #include<AT89X52.h>
- #define SPK P0_0 //定义方波输出口
- #define LED P1_1
- #define shumaguan P0 //定义数码管段码输出
- unsigned int tone1,tone2;
- /*****标准音符表*****/
- //用于使定时器初值变化以产生相应频率的定时
- unsigned char code yinfu[]={
- 0xfb,0xe9, //Do
- 0xfc,0x5c, //Re
- 0xfc,0xc1, //Mi
- 0xfc,0xef, //Fa
- 0xfd,0x45, //So
- 0xfd,0x92, //La
- 0xfd,0xd0, //Si
- 0xfd,0xee, //Do#
- 0xfa,0x14, //So低
- 0xfa,0xb9, //La低
- 0xfb,0x4d, //Si低
- 0x00,0x00 //音符之间的间隔,只要间隔时间小于65ms时,
- //喇叭不会发出声音,用作拍子之间的短暂停顿
- };
- /*****军港之夜音调表*****/
- unsigned char code shengri_tone[]={9,3,3,1,2,3,2,3,3,10,9,1,2,1,3,5,5,3,6,5,3,
- 3,3,2,1,2,3,2,3,11,9,10,11,10,1,11,3,3,11,10,11,10,11,3,3,11,
- 11,10,11,10,2,10,1,11,10,9,10,9,3,5,5,3,6,5,6,5,3,5,3,1,3,3,3,5,
- 3,5,5,3,3,2,3,2,11,10,11,10,9,3,3,5,5,3,6,5,6,5,3,5,3,1,3,
- 3,5,3,5,5,3,3,3,2,3,2,11,10,11,10,9,1 //0代表不发声,即停顿;数字即为音调
- };
- /*****军港之夜节拍表*****/
- unsigned char code shengri_beat[]={24,24,24,24,12,12,48,24,48,24,24,12,12,86,24,24,24,24,24,48,24,
- 48,12,12,24,12,12,86,48,24,24,12,12,48,24,24,24,24,24,12,12,72,24,24,24,24,
- 24,12,12,48,24,12,12,24,24,12,12,86,24,24,24,24,24,12,12,48,12,24,12,24,12,12,12,48,
- 24,24,24,24,24,12,12,48,24,12,12,24,24,86,24,24,24,24,24,12,12,48,12,24,12,24,24,
- 24,72,24,24,24,12,12,24,12,12,48,24,12,12,24,24,86 //节拍,即tone表各音调的延时
- };
- /*****自动演示音调表*****/
- unsigned char code yanshi_tone[]={ 1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,
- 8,0,7,0,6,0,5,0,4,0,3,0,2,0,1,0
- };
- /*****自动演示节拍表*****/
- unsigned char code yanshi_beat[]={ 48,1,48,1,48,1,48,1,48,1,48,1,48,1,48,2,
- 48,1,48,1,48,1,48,1,48,1,48,1,48,1,48,2
- };
- /*****15ms延时子程序,用于节拍*****/
- void delay(void)
- {
- unsigned char n=50;
- while(n--)
- {
- unsigned char i;
- for(i=0;i<125;i++);
- }
- }
- /*****定时器0初始化*****/
- void initTimer(void)
- {
- TMOD=0x01; //定时器0,工作方式1;定时器1,工作方式1
- TH0=tone1;
- TL0=tone2;
- }
- void timer0(void) interrupt 1
- {
- TH0=tone1;
- TL0=tone2;
- SPK=~SPK; //取反,以产生方波
- }
- /*****演奏子程序1*****/
- void play1(void)
- {
- unsigned char m=0;
- unsigned char s;
- unsigned char a=1;
- while(1)
- {
- EA=0;
- LED=0;
- a=shengri_tone[m]; //取音符
- s=shengri_beat[m]; //取节拍
- tone1=yinfu[2*a-2];
- tone2=yinfu[2*a-1];
- EA=1;
- while(s--)
- {
- delay();
- }
- LED=1;
- m++;
- if(m>=119) return; //数值是shengri相关表中的元素数量
- }
- }
- /*****演奏子程序2*****/
- void play2(void)
- {
- unsigned char m=0;
- unsigned char s;
- unsigned char a=1;
- while(1)
- {
- EA=0;
- LED=0;
- a=yanshi_tone[m];
- s=yanshi_beat[m];
- tone1=yinfu[2*a-2];
- tone2=yinfu[2*a-1];
- EA=1;
- while(s--)
- {
- delay();
- }
- LED=1;
- m++;
- if(m>=32) return;
- }
- }
- /*****按键检测*****/
- void check_key(void)
- {
- P2=0xff;
- P3=0xff; //设置为输入状态
- switch(P2) //检测按键,输出数码管、载入定时器初值、允许中断
- {
- case 0xfe:shumaguan=0xF9;tone1=0xfb;tone2=0x90;EA=1;break;
- case 0xfd:shumaguan=0xA4;tone1=0xfc;tone2=0xc;EA=1;break;
- case 0xfb:shumaguan=0xB0;tone1=0xfc;tone2=0x7b;EA=1;break;
- case 0xf7:shumaguan=0x99;tone1=0xfc;tone2=0xad;EA=1;break;
- case 0xef:shumaguan=0x92;tone1=0xfd;tone2=0xa;EA=1;break;
- case 0xdf:shumaguan=0x82;tone1=0xfd;tone2=0x5d;EA=1;break;
- case 0xbf:shumaguan=0xF8;tone1=0xfd;tone2=0xa7;EA=1;break;
- case 0x7f:play1();break;
- default: EA=0;SPK=0;shumaguan=0xff;//如果没有键按下则关闭中断和数码管
- }
- switch(P3)
- {
- case 0xfe:shumaguan=0x79;tone1=0xfd;tone2=0xc8;EA=1;break;
- case 0xfd:shumaguan=0x24;tone1=0xfe;tone2=0x6;EA=1;break;
- case 0xfb:shumaguan=0x30;tone1=0xfe;tone2=0x3e;EA=1;break;
- case 0xf7:shumaguan=0x19;tone1=0xfe;tone2=0x57;EA=1;break;
- case 0xef:shumaguan=0x12;tone1=0xfe;tone2=0x85;EA=1;break;
- case 0xdf:shumaguan=0x02;tone1=0xfe;tone2=0xaf;EA=1;break;
- case 0xbf:shumaguan=0x78;tone1=0xfe;tone2=0xd4;EA=1;break;
- case 0x7f:play2();break;
- default: EA=0;SPK=0;shumaguan=0xff;//如果没有键按下则关闭中断和数码管
- }
- }
- /*****主程序*****/
- void main(void)
- {
- initTimer();
- // shumaguan=0xff;
- TR0=1;
- ET0=1;
- SPK=0;
- while(1)
- {
- check_key();
- }
- }
复制代码
|