#include<reg51.h> #include<intrins.h> #define uchar unsigned char #define uint unsigned int sbit K1=P1^0; //播放和停止鍵 sbit SPK=P3^7; //蜂鳴器 uchar Song_Index=0,Tone_Index=0; //當前音樂段索引,音符索引 //數碼管段碼表 uchar codeDSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //標準音符頻率對應的延時表 uchar codeHI_LIST[]={0,226,229,232,233,236,238,240,241,242,244,245,246,247,248}; uchar codeLO_LIST[]={0,4,13,10,20,3,8,6,2,23,5,26,1,4,3}; //三段音樂的音符 uchar code Song[][50]= { {1,2,3,1,1,2,3,1,3,4,5,3,4,5,5,6,5,3,5,6,5,3,5,3,2,1,2,1,-1}, {3,3,3,4,5,5,5,5,6,5,3,5,3,2,1,5,6,53,3,2,1,1,-1}, {3,2,1,3,2,1,1,2,3,1,1,2,3,1,3,4,5,3,4,5,5,6,5,3,5,3,2,1,3,2,1,1,-1} }; //三段音樂的節拍 uchar code Len[][50]= { {1,1,1,1,1,1,1,1,1,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,2,-1}, {1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,2,-1}, {1,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,2,1,1,1,1,1,1,1,2,1,1,2,2,-1} }; //外部中斷0 void EX0_INT() interrupt 0 { TR0=0; //播放結束或者播放中途切換歌曲時停止播放 Song_Index=(Song_Index+1)%3; //跳到下一首的開頭 Tone_Index=0; P2=DSY_CODE[Song_Index]; //數碼管顯示當前音樂段號 } //定時器0中斷函數 void T0_INT() interrupt 1 { TL0=LO_LIST[Song[Song_Index][Tone_Index]]; TH0=HI_LIST[Song[Song_Index][Tone_Index]]; SPK=~SPK; } //延時 void DelayMS(uint ms) { uchart; while(ms--)for(t=0;t<120;t++); } //主程序 void main() { P2=0xc0; SPK=0; TMOD=0x00; //T0方式0 IE=0x83; IT0=1; IP=0x02; while(1) { while(K1==1); //未按鍵等待 while(K1==0); //等待釋放 TR0=1; //開始播放 Tone_Index=0; //從第0個音符開始 //播放過程中按下K1可提前停止播放(K1=0)。 //若切換音樂段會觸發外部中斷,導致TR0=0,播放也會停止 while(Song[Song_Index][Tone_Index]!=-1&&K1==1&&TR0==1) { DelayMS(300*Len[Song_Index][Tone_Index]); //播放延時(節拍) Tone_Index++; //當前音樂段的下一音符索引 } TR0=0; //停止播放 while(K1==0); //若提前停止播放,按鍵未釋放時等待 } }
|