我把程序加了注釋,去掉了讓人不好理解的和無實際作用的暫停函數,修正了音律賦值代碼后音準更準了,要換歌自己按前段演示的音符把簡譜編入音律符節拍數組即可,才學了2周單片機,這是我仔細消化后的改進了前輩的作業。
#include <REG51.H>#define uchar unsigned charsbit beepIO=P0^7; //定義蜂鳴器端口為p0^7,根據單片機實際蜂鳴器實際接口改變uchar m,n; //定義4個八度每八度12分音律共48音律uchar code T[49][2]={{0,0},//定義音律49個二維數組{0xF9,0x1F},{0xF9,0x82},{0xF9,0xDF},{0xFA,0x37},{0xFA,0x8A},{0xFA,0xD8},{0xFB,0x23},{0xFB,0x68},{0xFB,0xAA},{0xFB,0xE9},{0xFC,0x24},{0xFC,0x5B},{0xFC,0x8F},{0xFC,0xC1},{0xFC,0xEF},{0xFD,0x1B},{0xFD,0x45},{0xFD,0x6C},{0xFD,0x91},{0xFD,0xB4},{0xFD,0xD5},{0xFD,0xF4},{0xFE,0x12},{0xFE,0x2D},{0xFE,0x48},{0xFE,0x60},{0xFE,0x78},{0xFE,0x86},{0xFE,0xA3},{0xFE,0xB6},{0xFE,0xC9},{0xFE,0xDA},{0xFF,0xEB},{0xFE,0xFA},{0xFF,0x09},{0xFF,0x17},{0xFF,0x24},{0xFF,0x30},{0xFF,0x3C},{0xFF,0x47},{0xFF,0x51},{0xFF,0x5B},{0xFF,0x64},{0xFF,0x6D},{0xFF,0x75},{0xFF,0x7D},{0xFF,0x84},{0xFF,0x8B}};uchar code music[][2]={{0,4},//定義曲譜數組,前數為音律,后數為音符節拍 ,要換歌改變簡譜對應的音律號即可{0,1},{1,1},{3,1},{5,1},{6,1},{8,1},{10,1},{12,1},{13,1},//演示超低音八度 123457671{0,1},{13,1},{15,1},{17,1},{18,1},{20,1},{22,1},{24,1},{25,1},//演示低音八度12345671{0,1},{25,1},{27,1},{29,1},{30,1},{32,1},{34,1},{36,1},{37,1},//演示中音八度12345671{0,1},{37,1},{39,1},{41,1},{42,1},{44,1},{46,1},{48,2},//演示高音八度 1234567{0,4},{24,4},{24,4},{21,4},{19,4},{21,4},{14,8},{19,4},{21,4},{24,4},{21,4},{19,16},//記錄菊花臺簡譜歌詞:0553236 23532 天青色等煙雨 而我在等你{0,4},{24,4},{24,4},{21,4},{19,4},{21,4},{12,8},{19,4},{21,4},{24,4},{19,4},{17,16},//簡譜歌詞:0553235 23521 炊煙裊裊升起 隔江千萬里{0,4},{17,4},{19,4},{21,4},{24,4},{26,4},{24,4},{22,4},{24,4},{21,4},{21,4},{19,4},{19,16},//簡譜歌詞:01235654 53322 在平地書刻你房間上的飄影{0,4},{17,4},{19,4},{17,4},{17,4},{19,4},{17,4},{19,4},{19,4},{21,8},{24,4},{21,4},{21,12},//簡譜歌詞:就當我為遇見你伏筆{0,4},{24,4},{24,4},{21,4},{19,4},{21,4},{14,8},{19,4},{21,4},{24,4},{21,4},{19,16}, //簡譜歌詞:0553236 23532 天青色等煙雨 而我在等你{0,4},{24,4},{24,4},{21,4},{19,4},{21,4},{12,8},{19,4},{21,4},{24,4},{19,4},{17,16}, //簡譜歌詞:0553235 23521 月色被打撈起 掩蓋了結局{0,4},{17,4},{19,4},{21,4},{24,4},{26,4},{24,4},{22,4},{24,4},{21,4},{21,4},{19,4},{19,12},//簡譜歌詞:0123 5654 5332 25 322 11 如傳世的青花瓷在獨自美麗{12,4},{21,8},{19,8},{19,4},{17,20}, //簡譜歌詞:你眼帶笑意{0xFF,0xFF}}; //歌曲結尾標識void delay(uchar p) //延時函數 無符號字符型變量{uchar i,j; //定義無符號字符型變量J和Ifor(;p>0;p--) // 此處P值即主函數的n值節拍個數for(i=181;i>0;i--) //延時181*181個機器周期約25毫秒,即一個1/16節拍for(j=181;j>0;j--);} void T0_int() interrupt 1{beepIO=!beepIO; //蜂鳴器翻轉發聲TH0=T[m][0]; TL0=T[m][1]; //音律延時周期次數碼表賦給定時寄存器作為計數初始值,每TH0TL0個機器周期觸發蜂鳴器端口翻轉,演奏出不同音符}void main(){uchar i=0; //定義無符號字符型變量i,初始值為0TMOD=0x01; EA=1; ET0=1; //開啟T0定時16位方式,總中斷開啟,開啟T0外部中斷請求while(1) //開始曲譜演奏,循環無限重復{m=music[ i][0];n=music[ i][1]; //將音律號賦值給m, 將節拍號賦值給nif(m==0x00) //如果音律號為0,{TR0=0;delay(n);i++;} //關閉計時器,延遲n拍,將循環數I加1 ,準備讀下一個音符else if(m==0xFF) //否則如果音律數為FF{TR0=0;delay(30);i=0;} //開啟節拍延時30個1/16節拍,歌曲停頓2秒,將循環數I置0else if(m==music[i+1][0]) // 否則如果把下一個音律號數給變量m{TR0=1;delay(n);TR0=0;i++;} //定時器0打開延遲n拍,關閉定時器T0,讀下一個音符,循環數加1讀下一個音律else //音符若不為零{TR0=1;delay(n);i++;}//打開定時器,延時n個1/16拍,循環數I加1 ,準備演奏下一個音符}} |