- #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();
- }
- }
復制代碼
|