標(biāo)題: 單片機(jī)電子琴課程設(shè)計(jì)論文 [打印本頁(yè)]

作者: 51黑電子迷    時(shí)間: 2017-6-5 01:10
標(biāo)題: 單片機(jī)電子琴課程設(shè)計(jì)論文
《單片機(jī)原理及應(yīng)用》課程設(shè)計(jì)
一、        電子琴電路功能介紹及組成框圖
1、設(shè)計(jì)要求
由16個(gè)按鍵組成4×4鍵盤矩陣,設(shè)置成16個(gè)音,可隨意彈奏想要表現(xiàn)的音樂(lè)。按下鍵的同時(shí),顯示鍵號(hào);另外在沒(méi)有鍵按下時(shí)能播放一首熟悉的音樂(lè)。



二、硬件電路設(shè)計(jì)
1、總電路
2、各部分工作原理1 音頻電路原理
音頻電路原理為整個(gè)電子琴設(shè)計(jì)的核心原理,電路設(shè)計(jì)方法和編程方法都圍繞著電子琴的音頻產(chǎn)生、變化的原理來(lái)進(jìn)行。
音頻電路中包含一個(gè)發(fā)音裝置。利用電子琴的音頻脈沖和節(jié)拍的產(chǎn)生原理,通過(guò)P3.3口來(lái)控制發(fā)音裝置,產(chǎn)生音符和音樂(lè)信號(hào)。
1.1)音頻脈沖
音樂(lè)的產(chǎn)生主要是通過(guò)單片機(jī)的I/O口輸出高低不同的脈沖信號(hào)來(lái)控制蜂鳴器發(fā)音,要想產(chǎn)生音頻脈沖信號(hào),需要算出某一音頻的周期(1/頻率),然后將此周期除以2,即為半周期的時(shí)間。利用單片機(jī)定時(shí)器計(jì)時(shí)這個(gè)半個(gè)周期時(shí)間,每當(dāng)計(jì)時(shí)到后就將輸出脈沖的I/O口反相,然后重復(fù)計(jì)時(shí)此半周期時(shí)間再對(duì)I/O口反相,這樣就能在此I/O口上得到此頻率的脈沖。通常,利用單片機(jī)的內(nèi)部定時(shí)器0,工作在方式1下,改變計(jì)數(shù)初始值THO和TLO來(lái)實(shí)現(xiàn)。
例如,若單片機(jī)采用12MHz晶振,要產(chǎn)生頻率為587Hz的音頻脈沖時(shí),其音頻信號(hào)的脈沖周期 T=1/587=1703.5775μs,半周期的時(shí)間為852μs,因此只要令計(jì)數(shù)器計(jì)數(shù)=852μs/1μs=852,在每計(jì)數(shù)852時(shí)將I/O口反相,就可得到C調(diào)中音Re。
計(jì)數(shù)脈沖值與頻率的關(guān)系如下:

頻率Hz

周期us

簡(jiǎn)譜碼(定時(shí)初值)

音符

頻率Hz

周期

us

簡(jiǎn)譜碼(定時(shí)初值)

低1Do

262

3816

63628

高1Do

1047

955

65058

低2Re

294

3401

63835

高2Re

1175

851

65110

低3Mi

330

3030

64021

高3Mi

1319

758

65157

低4Fa

349

2865

64103

高4Fa

1397

751

65160

低5So

392

2551

64260

高5So

1568

637

65217

低6La

440

2272

64400

高6La

1760

568

65252

低7Si

494

2024

64524

高7Si

1967

508

65282

中1Do

523

1912

64580

中2Re

587

1703

64684

中3Mi

659

1517

64777

中4Fa

698

1432

64820

中5So

784

1275

64898

中6La

880

1136

64968

中7Si

988

1012

65030

1.2 節(jié)拍
每個(gè)音符使用一個(gè)字節(jié),字節(jié)的高四位代表音符的高低,低四位代表音符的節(jié)拍,表5-2為節(jié)拍與節(jié)拍碼的對(duì)照表。如果1拍為0.4s,1/4拍是0.1s只要設(shè)定延遲時(shí)間就可求得節(jié)拍的時(shí)間。假設(shè)1/4拍為1個(gè)延遲單位時(shí)間,那么1拍對(duì)應(yīng)的就是4個(gè)延遲單位時(shí)間,以此類推。所以只要求得1/4拍的延遲單位時(shí)間,其余的節(jié)拍就是它的倍數(shù),表5-3為1/4拍和1/8拍的時(shí)間設(shè)定。
不管采用哪種方法,當(dāng)歌曲結(jié)束時(shí),在發(fā)音計(jì)數(shù)值表(TABLE)中均需加上音樂(lè)結(jié)束符00H。
2)音符顯示
采用的共陰極7段數(shù)碼管作為音符顯示器。當(dāng)AT89C51執(zhí)行完按鍵掃描程序后,所得到的鍵號(hào)送至P0口,通過(guò)P0口進(jìn)而控制數(shù)碼管的音符字模的顯示。另外,P0口作為通用I/O口時(shí),需要外界上拉電阻。
3)矩陣式音符鍵盤
          采用矩陣式鍵盤,節(jié)省I/O口資源。矩陣式鍵盤的行線與列線的交叉處不相通,設(shè)置為按鍵,n條行線與m條列線,可構(gòu)成n*m個(gè)按鍵的鍵盤。
4)彈奏按鍵
音符按鍵采用外部中斷1的方式來(lái)實(shí)現(xiàn)。當(dāng)按鍵按下時(shí),調(diào)用中斷函數(shù)切斷音樂(lè)播放模式,進(jìn)入音符按鍵彈奏模式。
三、軟件設(shè)計(jì)
1、程序組成
(1.1)歌曲播放程序
首先,建立音樂(lè)代碼庫(kù):找出樂(lè)曲最低音和最高音范圍,然后確定音符表T的順序,把T值建立在數(shù)組 T[ ] 中,構(gòu)成發(fā)音符的計(jì)數(shù)值放在數(shù)組tab[ ]中,以音符節(jié)拍碼00H為音樂(lè)結(jié)束標(biāo)記。通過(guò)調(diào)用音樂(lè)代碼庫(kù)來(lái)實(shí)現(xiàn)演奏歌曲。
[音樂(lè)代碼庫(kù)]
[音樂(lè)播放程序]
(1.2)鍵盤音符獲取程序
鍵盤是人與單片機(jī)通信的重要接口。合適的鍵盤掃描程序能使單片機(jī)準(zhǔn)確的運(yùn)行。另外,按鍵按下時(shí),由于彈簧抖動(dòng)的原因,會(huì)對(duì)按鍵有無(wú)按下的判斷產(chǎn)生干擾,故需要采用適當(dāng)?shù)南斗椒ā1景咐捎密浖訒r(shí)的方法去抖動(dòng)。
[延時(shí)去抖動(dòng)]
[按鍵掃描]
(1.3)音符顯示程序
采用的共陰極7段數(shù)碼管作為音符顯示器,當(dāng)執(zhí)行完按鍵掃描程序后,所得到的鍵號(hào)送至P0口,通過(guò)P0口進(jìn)而控制數(shù)碼管的音符字模的顯示。
[音符獲取]
(1.4)彈奏模式程序
通過(guò)彈奏按鍵的按下來(lái)產(chǎn)生外部中斷,利用中斷來(lái)實(shí)現(xiàn)由歌曲播放模式轉(zhuǎn)到彈奏模式。
[外部中斷0函數(shù)]
[音符彈奏]
2、流程圖
四、設(shè)計(jì)總結(jié)(包括調(diào)試軟、硬件過(guò)程和體會(huì)、收獲)
附錄:
1. 仿真狀態(tài)圖
2. 程序清單

  1. #include <reg51.h>
  2. #include <absacc.h>
  3. #include <stdio.h>
  4. #include <math.h>
  5. #define uchar unsigned char
  6. #define uint unsigned int
  7. uchar S=0,T=0;        
  8. uchar SH;      
  9. uchar SL;
  10. uchar k, key;
  11. bit flag=1;   
  12. sbit SPK=P3^0;
  13. uchar code DSY_CODE[]= {0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71};
  14. uchar code music[]= {8,9,10,8,8,9,10,8,10,11,12,10,11,12,-1};
  15. uchar code Len[]= {1,1,1,1,1,1,1,1,1,1,2,1,1,2,-1};
  16. uint code tab[]= { 64580,64684,64777,64820,64898,64968,65030,
  17.                      65058,65110,65157,65178,65217,65252,65283};  
  18. //延時(shí)
  19. void delay1(uint ms)
  20. { uchar t;
  21.         while(ms--)
  22.         for (t=0;t<120;t++); }

  23. /* 鍵消抖延時(shí)*/
  24.         void delay(void)
  25.         {  uchar i;
  26.                 for (i=300;i>0;i--); }

  27. /* 鍵掃描函數(shù) */
  28. uchar getkey()
  29.         {
  30.         uchar scode,tcode;
  31.                 if ((P2&0xf0)==0xf0)
  32.                 return(0);
  33.                         scode = 0xfe;
  34.                                  while((scode&0x10)!=0)  
  35.                                 {                     P2 = scode;
  36.                                         if ((P2&0xf0)!=0xf0)  
  37.                                                 {         
  38.                                                  tcode = (P2&0xf0)|0x0f;                                                                                                                   return((~scode)+(~tcode)); }
  39.                                         else scode = (scode<<=1)|0x01;         }
  40.           }
  41. void EX0_INT() interrupt 0
  42. {   flag=0;   }
  43. void time0_int(void) interrupt 1 using 0
  44. {  
  45.         TH0 = SH;
  46.         TL0 = SL;
  47.         SPK=!SPK;
  48.         P0=DSY_CODE[k] ;   }
  49. void main(void) {
  50.         P0=0x3f;
  51.         IE=0x87;
  52.         TMOD=0x01;
  53.         IT0=1;
  54.         IT1=1;
  55.                 while(1)
  56.                 {
  57.                          P2 = 0xf0;                                
  58.                                 if ((P2&0xf0)!=0xf0)  
  59.                                            delay();                       
  60.                                 if ((P2&0xf0)!=0xf0)   
  61.                                  {     key = getkey();  
  62.                                         switch(key)              
  63.                                         {
  64.                                                 case 0x11:k = 0;break;  // 按鍵1
  65.                                                 case 0x21:k = 1;break;  //         按鍵2                                       
  66.                                                 case 0x41:k = 2;break;  // 按鍵3                                                
  67.                                                 case 0x81:k = 3;break;  // 按鍵4                                                
  68.                                                 case 0x12:k = 4; break;     // 按鍵5                                                
  69.                                                 case 0x22:k = 5;break;      // 按鍵6                                                
  70.                                                 case 0x42:k = 6;break;      // 按鍵7                                                
  71.                                                 case 0x82:k = 7;break;      // 按鍵8                                                
  72.                                                 case 0x14:k = 8;break;      // 按鍵9                                                
  73.                                                 case 0x24:k = 9;break;      // 按鍵10                                       
  74.                                                 case 0x44:k = 10;break;      // 按鍵11                                       
  75.                                                 case 0x84:k = 11;break;      // 按鍵12                                       
  76.                                                 case 0x18:k = 12;break;      // 按鍵13                                       
  77.                                                 case 0x28:k = 13;break;      // 按鍵14                                       
  78.                                                 case 0x48:k = 14;break;      // 按鍵15                                       
  79.                                                 case 0x88:k = 15;break;      // 按鍵16                                       
  80.                                                 default:break;
  81.                                                 }
  82.                                                  if(flag==0) {                                                                                                                SH = tab[k]/256;
  83.                                                      SL = tab[k]%256;
  84.                                                          TR0 = 1;           
  85.                                                          while ((P2&0xf0)!=0xf0);  
  86.                                                          SPK=1;
  87.                                                          TR0 = 0;                                                                                      }
  88.                                                 else
  89.                                                   { while(flag==1)
  90.                                                         {               
  91.                                                                         if (music[T]==-1)T=0;
  92.                                                                         SH=(tab[music[T]])/256;


  93. …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼

完整課設(shè)論文下載(word格式 可編輯)http://www.torrancerestoration.com/bbs/dpj-86870-1.html





作者: ssp7812    時(shí)間: 2017-6-5 07:37
學(xué)習(xí)一下,頂一個(gè),




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1