基本要求如下:
1. 通過單片機編程控制,對按下的按鍵進行識別,然后控制喇叭發聲。電子琴模式下1-7七個按鍵可彈出“哆、來、咪、發、梭、拉、西”。
2. 當喇叭發聲時,用一個數碼管反應音符。
附加要求如下:
1. 當音樂切換按鍵時,可切換播放某首曲子。
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.gif (93.74 KB, 下載次數: 26)
下載附件
2023-12-17 15:05 上傳
單片機源程序如下:
- /*******51單片機簡易電子琴 八音盒 設計***********/
- /*********do re mi fa so la si 高音do************/
- /******************內置3首歌*********************/
- /***《揮著翅膀的女孩》《同一首歌》《兩只蝴蝶》***/
- /*****************JJ電子直營店*******************/
- /********************原創設計********************/
- #include <REGX52.H> //調系統頭文件
- #define uchar unsigned char //uchar代替 unsigned char
- #define uint unsigned int //uint代替 unsigned char
-
- #define Key1 P2_0 //定義按鍵1(播放 "揮著翅膀的女孩")
- #define Key2 P2_1 //定義按鍵2(播放 "同一首歌")
- #define Key3 P2_2 //定義按鍵3(播放 "兩只蝴蝶")
- #define SMG P0 //定義數碼管顯示端
- #define Speak P2_4 //定義蜂鳴器接口
- uchar sth,stl; //定義全局變量 sth stl
- uint i,j; //定義循環變量i j
- uchar code table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,
- 0x88,0x83,0xC6,0xA1,0x86,0x8E};//定義數碼管顯示 0-9,A-F
- uchar code Music_hzcb[]={//《揮著翅膀的女孩》系統自帶歌曲音符
- 0x17,0x02, 0x17,0x03, 0x18,0x03, 0x19,0x02, 0x15,0x03,
- ............................
- 0x10,0x03, 0x15,0x00, 0xff,0xff };
-
- uchar code Music_Code[]={ //八個音符 do re mi fa so la si 高音do
- 0xf8,0x8b,0xf9,0x5b,0xfa,0x14,0xfa,0x66,
- 0xfb,0x03,0xfb,0x8f,0xfc,0x0b,0xfd,0xee};
- uchar const yinfu1[3][14]={ //低中高三種音符
- 0xf8,0x8b,0xf9,0x5b,0xfa,0x14,0xfa,0x66,0xfb,0x03,0xfb,0x8f,0xfc,0x0b,
- 0xfc,0x43,0xfc,0xab,0xfd,0x08,0xfd,0x33,0xfd,0x81,0xfd,0xc7,0xfe,0x05,
- 0xfb,0x21,0xfe,0x55,0xfe,0x84,0xfe,0x99,0xfe,0xc0,0xfe,0xe3,0xff,0x02};
- uchar const length[]={1,2,4,8,16,32,64}; //幾分音符查表(節拍)
- void delay_ms(uint time) //毫秒延時函數
- {
- uint z;
- uchar x,y;
- for(z=0;z<time;z++)
- for(x=5;x>0;x--)
- for(y=97;y>0;y--);
- }
- void Time0_Init() //定時器T0初始化函數
- {
- TMOD=0x01; //工作方式1
- TH0=sth; //定時器高八位賦初值
- TL0=stl; //定時器低八位賦初值
- ET0=1; //使能T0中斷
- EA=1; //打開全局中斷
- TR0=0; //關閉定時器T0
- }
- void main() //主函數入口
- {
- Time0_Init(); //定時器T0初始化
- Speak=1; //蜂鳴器端口置1 (讓蜂鳴器處于與電源5V斷電狀態)
- while(1) //無限循環
- {
- switch(P1) //switch語句判斷檢測 P1按鍵狀態
- {
- case 0xfe: //P1=0xfe "do"按鍵按下
- delay_ms(10); //延時去抖
- if(P1==0xfe) //再判斷"do"按鍵是否按下
- {
- SMG=table[1]; //數碼管顯示"1"
- i=0; //i置0
- TR0=0; //關閉定時器T0
- sth=Music_Code[2*i]; //定時器高八位賦值 "do"
- stl=Music_Code[2*i+1]; //定時器低八位賦值 "do"
- TR0=1; //啟動定時器T0
- for(j=0;j<=1000;j++) //軟件延時,在一定時間里檢測
- {
- delay_ms(10); //延時一下
- if(P1==0xfe) continue; //"do"按鍵按下,跳出(繼續發音)
- else break; //松開了,則返回
- }
- SMG=0xff; //關閉數碼管顯示
- Speak=1; //蜂鳴器端口置1 (讓蜂鳴器處于與電源5V斷電狀態)
- TR0=0; //關閉定時器T0
- for(;;)
- {
- while(P1==0xfe); //等待按鍵松開
- delay_ms(10); //延時去抖
- if(P1==0xfe) continue;
- else break; //確定松開,退出
- }
- TR0=0; //關閉定時器T0
- }
- break; //返回
- case 0xfd: //P1=0xfd "re"按鍵按下
- delay_ms(10); //延時去抖
- if(P1==0xfd) //再判斷"re"按鍵是否按下
- {
- SMG=table[2]; //數碼管顯示"2"
- i=1; //i置1
- TR0=0; //關閉定時器T0
- sth=Music_Code[2*i]; //定時器高八位賦值 "re"
- stl=Music_Code[2*i+1]; //定時器低八位賦值 "re"
- TR0=1; //啟動定時器T0
- for(j=0;j<=1000;j++) //軟件延時,在一定時間里檢測
- {
- delay_ms(10); //延時一下
- if(P1==0xfd) continue; //"re"按鍵按下,跳出(繼續發音)
- else break; //松開了,則返回
- }
- SMG=0xff; //關閉數碼管顯示
- Speak=1; //蜂鳴器端口置1 (讓蜂鳴器處于與電源5V斷電狀態)
- TR0=0; //關閉定時器T0
- for(;;)
- {
- while(P1==0xfd); //等待按鍵松開
- delay_ms(10); //延時去抖
- if(P1==0xfd) continue;
- else break; //確定松開,退出
- }
- }
- TR0=0; //關閉定時器T0
- break; //返回
- case 0xef: //P1=0xef "mi"按鍵按下
- delay_ms(10); //延時去抖
- if(P1==0xef) //再判斷"mi"按鍵是否按下
- {
- SMG=table[3]; //數碼管顯示"3"
- i=2; //i置2
- TR0=0; //關閉定時器T0
- sth=Music_Code[2*i]; //定時器高八位賦值 "mi"
- stl=Music_Code[2*i+1]; //定時器低八位賦值 "mi"
- TR0=1; //啟動定時器T0
- for(j=0;j<=1000;j++) //軟件延時,在一定時間里檢測
- {
- delay_ms(10); //延時一下
- if(P1==0xef) continue; //"mi"按鍵按下,跳出(繼續發音)
- else break; //松開了,則返回
- }
- SMG=0xff; //關閉數碼管顯示
- Speak=1; //蜂鳴器端口置1 (讓蜂鳴器處于與電源5V斷電狀態)
- TR0=0; //關閉定時器T0
- for(;;)
- {
- while(P1==0xef); //等待按鍵松開
- delay_ms(10); //延時去抖
- if(P1==0xef) continue;
- else break; //確定松開,退出
- }
- }
- TR0=0; //關閉定時器T0
- break; //返回
- default: break; //沒有P1沒有按鍵按下,返回
- }
- switch(P3) //switch語句判斷檢測 P3按鍵狀態
- {
- case 0xfe: //P3=0xfe "fa"按鍵按下
- delay_ms(10); //延時去抖
- if(P3==0xfe) //再判斷"fa"按鍵是否按下
- {
- SMG=table[4]; //數碼管顯示"4"
- i=3; //i置3
- TR0=0; //關閉定時器T0
- sth=Music_Code[2*i]; //定時器高八位賦值 "fa"
- stl=Music_Code[2*i+1]; //定時器低八位賦值 "fa"
- TR0=1; //啟動定時器T0
- for(j=0;j<=1000;j++) //軟件延時,在一定時間里檢測
- {
- delay_ms(10); //延時一下
- if(P3==0xfe) continue; //"fa"按鍵按下,跳出(繼續發音)
- else break; //松開了,則返回
- }
- SMG=0xff; //關閉數碼管顯示
- Speak=1; //蜂鳴器端口置1 (讓蜂鳴器處于與電源5V斷電狀態)
- TR0=0; //關閉定時器T0
- for(;;)
- {
- while(P3==0xfe); //等待按鍵松開
- delay_ms(10); //延時去抖
- if(P3==0xfe) continue;
- else break; //確定松開,退出
- }
- }
- TR0=0; //關閉定時器T0
- break; //返回
- case 0xf7: //P3=0xf7 "so"按鍵按下
- delay_ms(10); //延時去抖
- if(P3==0xf7) //再判斷"so"按鍵是否按下
- {
- SMG=table[5]; //數碼管顯示"5"
- i=4; //i置4
- TR0=0; //關閉定時器T0
- sth=Music_Code[2*i]; //定時器高八位賦值 "so"
- stl=Music_Code[2*i+1]; //定時器低八位賦值 "so"
- TR0=1; //啟動定時器T0
- for(j=0;j<=1000;j++) //軟件延時,在一定時間里檢測
- {
- delay_ms(10); //延時一下
- if(P3==0xf7) continue; //"so"按鍵按下,跳出(繼續發音)
- else break; //松開了,則返回
- }
- SMG=0xff; //關閉數碼管顯示
- Speak=1; //蜂鳴器端口置1 (讓蜂鳴器處于與電源5V斷電狀態)
- TR0=0; //關閉定時器T0
- for(;;)
- {
- while(P3==0xf7); //等待按鍵松開
- delay_ms(10); //延時去抖
- if(P3==0xf7) continue;
- else break; //確定松開,退出
- }
- }
- TR0=0; //關閉定時器T0
- break; //返回
- case 0xef: //P3=0xef "la"按鍵按下
- delay_ms(10); //延時去抖
- if(P3==0xef) //再判斷"la"按鍵是否按下
- {
- SMG=table[6]; //數碼管顯示"6"
- i=5; //i置5
- TR0=0; //關閉定時器T0
- sth=Music_Code[2*i]; //定時器高八位賦值 "la"
- stl=Music_Code[2*i+1]; //定時器低八位賦值 "la"
- TR0=1; //啟動定時器T0
- for(j=0;j<=1000;j++) //軟件延時,在一定時間里檢測
- {
- delay_ms(10); //延時一下
- if(P3==0xef) continue; //"la"按鍵按下,跳出(繼續發音)
- else break; //松開了,則返回
- }
- SMG=0xff; //關閉數碼管顯示
- Speak=1; //蜂鳴器端口置1 (讓蜂鳴器處于與電源5V斷電狀態)
- TR0=0; //關閉定時器T0
- for(;;)
- {
- while(P3==0xef); //等待按鍵松開
- delay_ms(10); //延時去抖
- if(P3==0xef) continue;
- else break; //確定松開,退出
- }
- }
- TR0=0; //關閉定時器T0
- break; //返回
- case 0xdf: //P3=0xdf "si"按鍵按下
- delay_ms(10); //延時去抖
- if(P3==0xdf) //再判斷"si"按鍵是否按下
- {
- SMG=table[7]; //數碼管顯示"7"
- i=6; //i置6
- TR0=0; //關閉定時器T0
- sth=Music_Code[2*i]; //定時器高八位賦值 "si"
- stl=Music_Code[2*i+1]; //定時器低八位賦值 "si"
- TR0=1; //啟動定時器T0
- for(j=0;j<=1000;j++) //軟件延時,在一定時間里檢測
- {
- delay_ms(10); //延時一下
- if(P3==0xdf) continue; //"si"按鍵按下,跳出(繼續發音)
- else break; //松開了,則返回
- }
- SMG=0xff; //關閉數碼管顯示
- Speak=1; //蜂鳴器端口置1 (讓蜂鳴器處于與電源5V斷電狀態)
- TR0=0; //關閉定時器T0
- for(;;)
- {
- while(P3==0xdf); //等待按鍵松開
- delay_ms(10); //延時去抖
- if(P3==0xdf) continue;
- else break; //確定松開,退出
- }
- }
- TR0=0; //關閉定時器T0
- break; //返回
- case 0xbf: //P3=0xbf "高音do"按鍵按下
- delay_ms(10); //延時去抖
- if(P3==0xbf) //再判斷"高音do"按鍵是否按下
- {
- SMG=table[1]&0x7f; //數碼管顯示"1"帶小數點(1.)
- i=7; //i置7
- TR0=0; //關閉定時器T0
- sth=Music_Code[2*i]; //定時器高八位賦值 "高音do"
- stl=Music_Code[2*i+1]; //定時器低八位賦值 "高音do"
- TR0=1; //啟動定時器T0
- for(j=0;j<=1000;j++) //軟件延時,在一定時間里檢測
- {
- delay_ms(10); //延時一下
- if(P3==0xbf) continue; //"高音do"按鍵按下,跳出(繼續發音)
- else break; //松開了,則返回
- }
- SMG=0xff; //關閉數碼管顯示
- Speak=1; //蜂鳴器端口置1 (讓蜂鳴器處于與電源5V斷電狀態)
- TR0=0; //關閉定時器T0
- for(;;)
- {
- while(P3==0xbf); //等待按鍵松開
- delay_ms(10); //延時去抖
- if(P3==0xbf) continue;
- else break; //確定松開,退出
- }
- }
- TR0=0; //關閉定時器T0
- break; //返回
- default: break; //沒有P3沒有按鍵按下,返回
- }
-
- if(Key1==0) //按鍵1按下(播放 "揮著翅膀的女孩")
- {
- delay_ms(10); //延時去抖
- if(Key1==0) //再判斷按鍵1是否按下
- {
- SMG=table[10]; //數碼管顯示"A"
- for(i=0;Music_hzcb[i]!=0xff;i++) //for循環語句
- { //Music_hzcb[]=0ff時,跳出for循環語句,停止播放音樂
- sth=yinfu1[(Music_hzcb[i]%100)/10-1][((Music_hzcb[i]%10)-1)*2]; //定時器高八位賦值
- stl=yinfu1[(Music_hzcb[i]%100)/10-1][((Music_hzcb[i]%10)-1)*2+1];//定時器低八位賦值
- i++; //i加1
- TR0=1; //啟動定時器T0
- delay_ms(4*500/length[Music_hzcb[i]%10]); //確定幾分音符(節拍)
- TR0=0; //節拍結束,關閉定時器T0
- }
- SMG=0xff; //關閉數碼管顯示
- Speak=1; //蜂鳴器端口置1 (讓蜂鳴器處于與電源5V斷電狀態)
- for(;;)
- {
- while(Key1==0); //等待按鍵松開
- delay_ms(10); //延時去抖
- if(Key1==0) continue;
- else break; //確定松開,退出
- }
- }
- }
- if(Key2==0) //按鍵2按下(播放 "同一首歌")
- {
- delay_ms(10); //延時去抖
- if(Key2==0) //再判斷按鍵2是否按下
- {
- SMG=table[11]; //數碼管顯示"B"
- for(i=0;Music_tyshg[i]!=0xff;i++) //for循環語句
- { //Music_tyshg[]=0ff時,跳出for循環語句,停止播放音樂
- sth=yinfu1[(Music_tyshg[i]%100)/10-1][((Music_tyshg[i]%10)-1)*2]; //定時器高八位賦值
- stl=yinfu1[(Music_tyshg[i]%100)/10-1][((Music_tyshg[i]%10)-1)*2+1];//定時器低八位賦值
- i++; //i加1
- TR0=1; //啟動定時器T0
- delay_ms(4*500/length[Music_tyshg[i]%10]); //確定幾分音符(節拍)
- TR0=0; //節拍結束,關閉定時器T0
- }
- SMG=0xff; //關閉數碼管顯示
- Speak=1; //蜂鳴器端口置1 (讓蜂鳴器處于與電源5V斷電狀態)
- for(;;)
- {
- while(Key2==0); //等待按鍵松開
- delay_ms(10); //延時去抖
- if(Key2==0) continue;
- else break; //確定松開,退出
- }
- }
- }
- if(Key3==0) //按鍵3按下(播放 "兩只蝴蝶")
- {
- delay_ms(10); //延時去抖
- if(Key3==0) //再判斷按鍵3是否按下
- {
- SMG=table[12]; //數碼管顯示"C"
- for(i=0;Music_lzhhd[i]!=0xff;i++) //for循環語句
- { //Music_lzhhd[]=0ff時,跳出for循環語句,停止播放音樂
- sth=yinfu1[(Music_lzhhd[i]%100)/10-1][((Music_lzhhd[i]%10)-1)*2]; //定時器高八位賦值
- stl=yinfu1[(Music_lzhhd[i]%100)/10-1][((Music_lzhhd[i]%10)-1)*2+1];//定時器低八位賦值
- i++; //i加1
- TR0=1; //啟動定時器T0
- delay_ms(4*500/length[Music_lzhhd[i]%10]); //確定幾分音符(節拍)
- TR0=0; //節拍結束,關閉定時器T0
- }
- SMG=0xff; //關閉數碼管顯示
- Speak=1; //蜂鳴器端口置1 (讓蜂鳴器處于與電源5V斷電狀態)
- for(;;)
- {
- while(Key3==0); //等待按鍵松開
- delay_ms(10); //延時去抖
- if(Key3==0) continue;
- else break; //確定松開,退出
- }
- }
- }
- }
- }
- /**********定時器T0中斷服務函數**********/
- void time0() interrupt 1
- {
- TR0=0; //關閉定時器T0
- TH0=sth; //定時器高八位賦初值
- TL0=stl; //定時器低八位賦初值
- Speak=!Speak; //蜂鳴器端口取反
- TR0=1; //啟動定時器T0
- }
復制代碼
仿真程序51hei附件下載:
基于51單片機電子琴的設計.7z
(76.03 KB, 下載次數: 42)
2023-12-17 15:07 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|