我用stc12c5a60s2單片機做的 和你要求的功能差不多基本上改改晶振值就行 了
- /****************************
- 表白神器 音樂盒
- ****************************
- 晶振值33.1776MHz
- 功能簡介:K16控制暫停與繼續(xù)
- K4 上一曲
- K12下一曲
- 數(shù)碼管顯示當前歌曲序號
- ****************************
- 歌曲分別是:
- 紙短情長
- 兩只老虎
- 祝你生日快樂歌
- 小星星
- ****************************/
- #include <stc12c5a60s2.h>
- #define Xtal 33177600 //賦晶振值
- #define All 4 //歌曲總數(shù)
- sbit BUZZ = P1^3; //蜂鳴器控制引腳
- sbit KEY = P2^4; //按鍵定義
- sbit KEY4 = P2^7;
- sbit KEY12 = P2^5;
- sbit ADDR0 = P2^0; //數(shù)碼管顯示控制
- sbit ADDR1 = P2^1;
- sbit ADDR2 = P2^2;
- sbit ENLED = P1^1; //總線收發(fā)器
- bit KeySta = 1; //當前按鍵狀態(tài)
- bit KeySta4 = 1;
- bit KeySta12 = 1;
- bit backup = 1; //默認彈起時時一
- bit backup4 = 1;
- bit backup12 = 1;
- bit cntkey = 0; //判斷暫停還是播放
- bit breakflage = 0;//用按鍵改變歌曲標志
- unsigned char keybuf = 0xFF;
- unsigned char keybuf4 = 0xFF;
- unsigned char keybuf12 = 0xFF;
- unsigned char Num = 1; //第幾首歌
- unsigned char sizeofNote;//節(jié)拍的多少
-
- extern void Delay_ms(unsigned int ms);//延時函數(shù)
-
- void PlayControl(unsigned char Num);//歌曲選擇函數(shù)
- void Play();//演奏函數(shù)
- unsigned char code LedChar[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E};//數(shù)碼管顯示字符轉換表
- unsigned int code NoteFrequ[] = { //中音1-7低音1-7和高音1-7對應頻率列表
- 523, 587, 659, 698, 784, 880, 988, //中音1-7
- 1047, 1175, 1319, 1397, 1568, 1760, 1976, //高音1-7
- 262, 294, 330, 349, 392, 440, 494,300//低音1-7 最后一個純屬湊數(shù)
- };
- unsigned int code NoteReload[] = { //中音1-7和高音1-7對應的定時器重載值
- 65536 - (Xtal/12) / (523*2), //中音1
- 65536 - (Xtal/12) / (587*2), //2
- 65536 - (Xtal/12) / (659*2), //3
- 65536 - (Xtal/12) / (698*2), //4
- 65536 - (Xtal/12) / (784*2), //5
- 65536 - (Xtal/12) / (880*2), //6
- 65536 - (Xtal/12) / (988*2), //7
- 65536 - (Xtal/12) / (1047*2), //高音1
- 65536 - (Xtal/12) / (1175*2), //2
- 65536 - (Xtal/12) / (1319*2), //3
- 65536 - (Xtal/12) / (1397*2), //4
- 65536 - (Xtal/12) / (1568*2), //5
- 65536 - (Xtal/12) / (1760*2), //6
- 65536 - (Xtal/12) / (1976*2), //7
- 65536 - (Xtal/12) / (262*2), //低音1
- 65536 - (Xtal/12) / (294*2), //2
- 65536 - (Xtal/12) / (330*2), //3
- 65536 - (Xtal/12) / (349*2), //4
- 65536 - (Xtal/12) / (392*2), //5
- 65536 - (Xtal/12) / (440*2), //6
- 65536 - (Xtal/12) / (494*2), //7
- 65536 - (Xtal/12) / (300*2), //純屬湊數(shù)
- };
- unsigned char *SongNote, *SongBeat;//指針
- unsigned char code XiaoXingXingNote[] = { //小星星
- 1, 1, 5, 5, 6, 6, 5, 4, 4, 3, 3, 2, 2, 1,
- 5, 5, 4, 4, 3, 3, 2, 5, 5, 4, 4, 3, 3, 2 ,
- 1, 1, 5, 5, 6, 6, 5, 4, 4, 3, 3, 2, 2, 1, 0xff };
- unsigned char code XiaoXingXingBeat[] = {
- 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 8,
- 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 8,
- 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 8,};
- unsigned char code TwoTigerNote[] = { //兩只老虎音符表
- 1, 2, 3, 1, 1, 2, 3, 1, 3, 4, 5, 3, 4, 5,
- 5,6, 5,4, 3, 1, 5,6, 5,4, 3, 1, 1, 5, 1, 1, 5, 1,0xff};
- unsigned char code TwoTigerBeat[] = { //兩只老虎節(jié)拍表,4表示一拍,1就是1/4拍,8就是2拍
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 8,
- 3,1, 3,1, 4, 4, 3,1, 3,1, 4, 4, 4, 4, 8, 4, 4, 8,
- };
- unsigned char code HappybirthdayNote[] = { //生日快樂歌
- 5, 5, 6, 5, 8, 7, 22, 5, 5, 6, 5, 9, 8, 5, 5, 12, 10, 8, 7, 6, 11, 11, 10, 8, 9, 8,0xff };
- unsigned char code HappybirthdayBeat[] = {
- 2, 2, 4, 4, 4, 4, 4, 2, 2, 4, 4, 4, 8, 2, 2, 4, 4, 4, 4, 8, 2, 2, 4, 4, 4, 8};
- unsigned char code ZhiduanqingchangNote[] = { //紙短情長
- //8, 9, 10, 9, 8, 6, 22, 11, 10, 9, 22, 7, 8, 9, 7, 7, 5, 22, 7, 9, 8, 8, 3, 4, 2, 3, 1, 1, 5, 2, //前奏
- 19, 3, 3, 3, 2, 3, 1, 2, 2, 2, 1, 2, 5, 1, 1, 1, 20, 1, 20, 19, 2, 2, 2, 3, 20, 19, 4, 4, 4, 3, 4, 1, 2, 2, 2, 1, 2, 5,
- 1, 1, 1, 20, 1, 20, 3, 2, 2, 1, 1, 22, 22, 22, 1, 1, 2, 3, 3, 3, 22, 3, 2, 1, 21, 6, 5, 22, 5, 6, 7, 8, 3, 3, 22, 8, 7, 8,
- 7, 3, 5, 5, 6, 8, 5, 6, 22, 6, 5, 4,5, 3, 2, 1, 20, 1, 3, 2, 2, 1, 2, 5, 1, 2, 5, 22, 22, 22, 1, 1, 2,
- 3, 3, 2, 3, 22, 3, 2, 1, 5, 5, 3, 5, 22, 5, 6, 7, 8, 8, 8, 8, 8, 7, 6, 7, 6, 3, 5, 5, 5, 6, 8, 5, 6, 22, 6, 5, 4,
- 5, 3, 2, 1, 6, 1, 3, 2, 2, 1, 2, 1, 20, 1, 22, 22, 20, 1, 3, 2, 2, 22, 2, 1, 2, 1, 1, 22, 20, 1, 1, 0xff};
- unsigned char code ZhiduanqingchangBeat[] = {
- //2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 8, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 8, 8, 12, 4, 5, 4, 8, 8, 4, //前奏
- 8, 2, 2, 2, 2, 2, 5, 2, 2, 2, 2, 2, 5, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 4, 5, 2, 2, 2, 2, 2, 5,
- 2, 2, 2, 2, 2, 5, 2, 2, 2, 2, 8, 4, 4, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2,
- 4, 2, 5, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 4, 2, 5, 1, 1, 2, 2, 2, 2, 2, 4, 2, 16, 16,4, 4, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 4, 2, 2, 2, 4, 2, 2, 2, 2, 2,
- 2, 4, 2, 5, 1, 1, 2, 2, 2, 2, 2, 4, 1, 12, 4, 2, 1, 1, 2, 2, 8, 2, 1, 1, 2, 2, 8, 2, 2, 12, 16};
- bit enable = 1; //蜂鳴器發(fā)聲使能標志
- bit tmrflag = 0; //定時器中斷完成標志
- unsigned char T0RH = 0xFF; //T0重載值的高字節(jié)
- unsigned char T0RL = 0x00; //T0重載值的低字節(jié)
- void main()
- {
-
- EA = 1; //使能全局中斷
- TMOD = 0x11; //配置T0,T1工作在模式1
- TH0 = T0RH;
- TL0 = T0RL;
- ET0 = 1; //使能T0中斷
- ET1 = 1; //使能T1中斷
- TR1 = 1; //啟動T1
- ENLED = 0x00; //使能總線收發(fā)器
- ADDR2=1; ADDR1=0; ADDR0=1;//選擇最右邊的數(shù)碼管
- P23 = 0; //啟用KEY
-
- while (1)
- {
- P0 = LedChar[Num]; //數(shù)碼管顯示當前歌曲序號
- PlayControl(Num);
- if(breakflage == 1)
- breakflage = 0;
- else
- Delay_ms(500);
- }
- }
- void PlayControl(unsigned char Num)
- {
- switch(Num)
- {
- case 4:SongNote = XiaoXingXingNote; SongBeat = XiaoXingXingBeat; sizeofNote = sizeof(XiaoXingXingNote); Play();break;
- case 2:SongNote = TwoTigerNote; SongBeat =TwoTigerBeat; sizeofNote = sizeof(TwoTigerNote); Play();break;
- case 3:SongNote = HappybirthdayNote; SongBeat =HappybirthdayBeat; sizeofNote = sizeof(HappybirthdayNote); Play();break;
- case 1:SongNote = ZhiduanqingchangNote;SongBeat =ZhiduanqingchangBeat;sizeofNote = sizeof(ZhiduanqingchangNote);Play();break;
- default:break;
- }
- }
- /* 演奏函數(shù) */
- void Play()//演奏函數(shù)
- {
- unsigned char beat; //當前節(jié)拍索引
- unsigned char note; //當前節(jié)拍對應的音符
- unsigned int time = 0; //當前節(jié)拍計時
- unsigned int beatTime = 0; //當前節(jié)拍總時間
- unsigned int soundTime = 0; //當前節(jié)拍需發(fā)聲時間
- for (beat=0; beat<sizeofNote; ) //用節(jié)拍索引作為循環(huán)變量
- {
- if(breakflage == 1)
- break;
- while (!tmrflag); //每次定時器中斷完成后,檢測并處理節(jié)拍
- tmrflag = 0;
- if (time == 0) //當前節(jié)拍播完則啟動一個新節(jié)拍
- {
- if(breakflage == 1)
- break;
- note = SongNote[beat] - 1;
- if(note == 0xfe)
- {
- if(Num == All)
- Num = 1;
- else
- Num++;
- break;
- }
- T0RH = NoteReload[note] >> 8;
- T0RL = NoteReload[note];
- beatTime = (SongBeat[beat] * NoteFrequ[note]) >> 2;//計算節(jié)拍總時間,右移2位相當于除4,移位代替除法可以加快執(zhí)行速度
- soundTime = beatTime - (beatTime >> 2);//計算發(fā)聲時間,
- enable = 1; //指示蜂鳴器開始發(fā)聲
- if (note == 21)//簡譜的0 等待
- enable =0;
- time++;
- }
- else //當前節(jié)拍未播完則處理當前節(jié)拍
- {
- if (time >= beatTime) //當前持續(xù)時間到達節(jié)拍總時間時歸零,
- { //并遞增節(jié)拍索引,以準備啟動新節(jié)拍
- time = 0;
- beat++;
- }
- else //當前持續(xù)時間未達到總時間時,
- {
- time++; //累加時間計數(shù)
- if (time == soundTime) //到達發(fā)聲時間后,指示關閉蜂鳴器,
- { //插入0.25*總時間的靜音間隔,
- enable = 0; //用以區(qū)分連續(xù)的兩個節(jié)拍
- }
- }
- }
- }
- }
- /*控制蜂鳴器發(fā)聲 */
- void InterruptTimer0() interrupt 1
- {
- TH0 = T0RH; //重新加載重載值
- TL0 = T0RL;
- tmrflag = 1;
- if (enable) //使能時反轉蜂鳴器控制電平
- BUZZ = ~BUZZ;
- else //未使能時關閉蜂鳴器
- BUZZ = 1;
- }
- /*按鍵掃描*/
- void InterruptTimer1() interrupt 3 //按鍵部分參看之前的帖子 帶有計次功能的秒表
- {
- TH1 = 0xC9;
- TL1 = 0xEA;
-
- keybuf = (keybuf<<1) | KEY;
- if (keybuf == 0x00)
- KeySta = 0;
- else if (keybuf == 0xFF)
- KeySta = 1;
- else{}
-
- keybuf4 = (keybuf4<<1) | KEY4;
- if (keybuf4 == 0x00)
- KeySta4 = 0;
- else if (keybuf4 == 0xFF)
- KeySta4 = 1;
- else{}
-
- keybuf12= (keybuf12<<1) | KEY12;
- if (keybuf12 == 0x00)
- KeySta12 = 0;
- else if (keybuf12 == 0xFF)
- KeySta12 = 1;
- else{}
-
- if (KeySta != backup)
- {
- if (backup == 0)
- {
- cntkey=~cntkey;
- TR0 = cntkey;
- }
- backup = KeySta;
- }
- if (KeySta4 != backup4)
- {
- if(backup4 ==0)
- {
- breakflage = 1;
- if(Num <All)
- Num++;
- else if(Num == All)
- Num =1;
- P0 = LedChar[Num];
- }
- backup4 = KeySta4;
- }
-
- if (KeySta12 != backup12)
- {
- if(backup12 ==0)
- {
- breakflage = 1;
- if(Num >1)
- Num--;
- else if(Num == 1)
- Num =All;
- P0 = LedChar[Num];
- }
- backup12 = KeySta12;
- }
-
- }
復制代碼 |