找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6140|回復(fù): 1
打印 上一主題 下一主題
收起左側(cè)

單片機(jī)電子琴課程設(shè)計論文

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:161768 發(fā)表于 2017-6-5 01:10 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
《單片機(jī)原理及應(yīng)用》課程設(shè)計
一、        電子琴電路功能介紹及組成框圖
1、設(shè)計要求
由16個按鍵組成4×4鍵盤矩陣,設(shè)置成16個音,可隨意彈奏想要表現(xiàn)的音樂。按下鍵的同時,顯示鍵號;另外在沒有鍵按下時能播放一首熟悉的音樂。



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

頻率Hz

周期us

簡譜碼(定時初值)

音符

頻率Hz

周期

us

簡譜碼(定時初值)

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

  23. /* 鍵消抖延時*/
  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. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復(fù)制代碼

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




分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

沙發(fā)
ID:205887 發(fā)表于 2017-6-5 07:37 | 只看該作者
學(xué)習(xí)一下,頂一個,
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表