版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、<p> 《單片機應用與仿真訓練》設計報告</p><p> 模擬電子琴發(fā)聲控制系統(tǒng)</p><p><b> 摘要</b></p><p> 本設計是基于AT89S52單片機的電子琴的電路設計方法而制作。該方法利用單片機定時器來產(chǎn)生固定頻率的方波信號以推動喇叭發(fā)出旋律。并使用LED顯示器來顯示音階輸入的相關消息,然后通過按下
2、鍵盤組中的相對按鍵使喇叭發(fā)出相對音階單音,并自動存儲所輸入的單音,之后再一起自動演奏出來,從而實現(xiàn)具有存儲功能的電子琴系統(tǒng)。本設計實現(xiàn)的功能是利用蜂鳴器作為發(fā)聲部件,兩個數(shù)碼管作為顯示部件,設置11個按鍵,實現(xiàn)高音、中音、低音的1、2、3、4、5、6、7的發(fā)音,并存儲一首歌的內容,可以實現(xiàn)自動播放。它具有7個音階的鍵盤,分別為DO、RE、MI、FA、SO、LA、SI。每個音階都對應著不同的頻率,這樣,我們就可以利用不同的頻率組合構成我們
3、想要的音樂。對于單片機來產(chǎn)生不同的頻率非常方便,我們可以利用單片機的定時/計數(shù)器T0來產(chǎn)生這樣的方波頻率信號,因此,我們只要把一首歌曲的音階對應頻率關系弄正確即可。用戶可以根據(jù)樂譜在鍵盤上進行演奏,音樂發(fā)生器會根據(jù)用戶的彈奏,通過揚聲器將音樂播放出來。</p><p> 介紹了一種基于AT89S52單片機的電子琴的電路設計方法。該方法利用單片機定時器來產(chǎn)生固定頻率的方波信號以推動喇叭發(fā)出旋律。然后通過按下鍵盤組
4、中的相對按鍵使喇叭發(fā)出相對音階單音,并自動存儲所輸入的單音,之后再一起自動演奏出來,從而實現(xiàn)具有存儲功能的電子琴系統(tǒng)。</p><p> 關鍵詞:單片機、電子琴、音階、頻率</p><p><b> 目錄</b></p><p><b> 摘要2</b></p><p><b>
5、 1、概述4</b></p><p> 1.1電子琴概述4</p><p> 1.2電子琴系統(tǒng)原理4</p><p> 1.3設計任務及要求4</p><p> 2、系統(tǒng)總體方案及硬件設計5</p><p> 2.1 系統(tǒng)硬件組成5</p><p> 2.11
6、 AT89S52簡介5</p><p> 2.12 音樂播放部分8</p><p> 2.13電子琴彈奏部分8</p><p> 2.2 具體發(fā)音原理8</p><p> 2.3 各部分電路圖10</p><p> 2.31 晶振10</p><p> 2.32 復
7、位電路10</p><p> 2.33 按鍵11</p><p> 2.34 發(fā)音11</p><p><b> 3、軟件設計12</b></p><p><b> 3.1流程圖12</b></p><p> 3.2 主程序代碼13</p>
8、;<p> 4、Proteus軟件仿真13</p><p> 5、課程設計體會13</p><p><b> 參考文獻14</b></p><p> 附錄1 源程序代碼15</p><p> 附錄2 仿真圖23</p><p><b> 1 概述<
9、;/b></p><p><b> 1.1 電子琴概述</b></p><p> 電子琴又稱作電子鍵盤,屬于電子樂器(區(qū)別于電聲樂器),發(fā)音音量可以自由調節(jié)。音域較寬,和聲豐富,甚至可以演奏出一個管弦樂隊的效果,表現(xiàn)力極其豐富。它還可模仿多種音色,甚至可以奏出常規(guī)樂器所無法發(fā)出的聲音(如合唱聲,風雨聲,宇宙聲等)。另外,電子琴在獨奏時,還可隨意配上類似打擊樂
10、音響的節(jié)拍伴奏,適合于演奏節(jié)奏性較強的現(xiàn)代音樂。</p><p> AT89S52是一種低功耗、高性能CMOS 8位微控制器,具有8K 在系統(tǒng)可編程Flash 存儲器。使用Atmel 公司高密度非易失性存儲器技術制造,與工業(yè)80C51 產(chǎn)品指令和引腳完全兼容。片上Flash允許程序存儲器在系統(tǒng)可編程,亦適于常規(guī)編程器。在單芯片上,擁有靈巧的8 位CPU 和在系統(tǒng)可編程Flash,使得AT89S52在眾多嵌入式控
11、制應用系統(tǒng)中得到廣泛應用。本文利用AT89C51 單片機的強大功能,通過軟件產(chǎn)生不同頻率的聲音信號,經(jīng)相應的放大電路后,在揚聲器中發(fā)出8個音節(jié)??梢詮椬喑霾煌那?。</p><p> 1.2 電子琴系統(tǒng)原理</p><p> 由于一首音樂是許多不同的音階組成的,而每個音階對應著不同的頻率,這樣我們就可以利用不同的頻率的組合,即可構成我們所想要的音樂了,當然對于單片機來產(chǎn)生不同的頻率非
12、常方便,我們可以利用單片機的定時/計數(shù)器T0來產(chǎn)生這樣方波頻率信號,因此,我們只要把一首歌曲的音階對應頻率關系弄正確即可。只要向若將不同的音節(jié)與一定的節(jié)拍組合在一起形成一定的曲調,因此只要一單片機I/0口,通過軟件,控制其輸出不同頻率的信號,就可以產(chǎn)生8個基本音節(jié)。將音節(jié)以一定的節(jié)拍進行組合,便可以產(chǎn)生歌曲。樂曲中每一音符對應著確定的頻率。如果單片機某個口線輸出“高~低”電平的頻率和某個音符的頻率一樣,那么將此口線接上喇叭就可以發(fā)出此音
13、。</p><p> 1.3 設計任務及要求</p><p> 本系統(tǒng)分為兩個部分,一個是音樂播放,另一個就是電子琴彈奏。通過開 控制播放音樂或者進行電子琴彈奏。本系統(tǒng)利用蜂鳴器作為發(fā)聲部件,當播放音樂時,彈奏按鍵無效;當進行彈奏時,設置10個按鍵,實現(xiàn)高音、中音、低音的1、2、3、4、5、6、7的發(fā)音,兩個數(shù)碼管作為顯示部件,顯示輸入的信息。</p><p>
14、 2 系統(tǒng)總體方案及硬件設計</p><p><b> 2.1硬件組成</b></p><p> 2.11 AT89S52簡介</p><p><b> 1.概述</b></p><p> AT89S52是一種低功耗、高性能CMOS 8位微控制器,具有8K 在系統(tǒng)可編程Flash 存儲器。
15、使用Atmel 公司高密度非易失性存儲器技術制造,與工業(yè)80C51 產(chǎn)品指令和引腳完全兼容。片上Flash允許程序存儲器在系統(tǒng)可編程,亦適于常規(guī)編程器。在單芯片上, </p><p> 圖2-2 AT89S52單片機 擁有靈巧的8 位CPU 和 在系統(tǒng)可編程Flash,使得AT89S52在眾多嵌入式控制應用系統(tǒng)中得到廣泛應用。</p><p><b&g
16、t; 2.主要性能</b></p><p> 與MCS-51單片機產(chǎn)品兼容; </p><p> 8K字節(jié)在系統(tǒng)可編程Flash存儲器; </p><p> 1000次擦寫周期; </p><p> 全靜態(tài)操作:0Hz-33MHz; </p><p> 三級加密程序存儲器; </p>
17、<p> 32個可編程I/O口線; </p><p> 三個16位定時器/計數(shù)器; </p><p><b> 六個中斷源; </b></p><p> 全雙工UART串行通道; </p><p> 低功耗空閑和掉電模式; </p><p> 掉電后中斷可喚醒; <
18、/p><p><b> 看門狗定時器; </b></p><p><b> 雙數(shù)據(jù)指針; </b></p><p><b> 掉電標識符 。</b></p><p><b> 3.管腳說明 </b></p><p> P0 口
19、:P0口是一個8位漏極開路的雙向I/O口。作為輸出口,每位能驅動8個TTL邏 輯電平。對P0端口寫“1”時,引腳用作高阻抗輸入。 當訪問外部程序和數(shù)據(jù)存儲器時,P0口也被作為低8位地址/數(shù)據(jù)復用。在這種模式下, P0不具有內部上拉電阻。 在flash編程時,P0口也用來接收指令字節(jié);在程序校驗時,輸出指令字節(jié)。程序校驗 時,需要外部上拉電阻。 </p><p> P1 口:P1 口是一個具有內部上拉電阻的8 位
20、雙向I/O 口,p1 輸出緩沖器能驅動4 個 TTL 邏輯電平。對P1 端口寫“1”時,內部上拉電阻把端口拉高,此時可以作為輸入 口使用。作為輸入使用時,被外部拉低的引腳由于內部電阻的原因,將輸出電流(IIL)。 </p><p> 此外,P1.0和P1.1分別作定時器/計數(shù)器2的外部計數(shù)輸入(P1.0/T2)和定時器/計數(shù)器2 的觸發(fā)輸入(P1.1/T2EX)。 在flash編程和校驗時,P1口接收低8位地址
21、字節(jié)。 </p><p><b> 引腳號第二功能: </b></p><p> P1.0 T2(定時器/計數(shù)器T2的外部計數(shù)輸入),時鐘輸出 </p><p> P1.1 T2EX(定時器/計數(shù)器T2的捕捉/重載觸發(fā)信號和方向控制) </p><p> P1.5 MOSI(在系統(tǒng)編程用) </p>
22、<p> P1.6 MISO(在系統(tǒng)編程用) </p><p> P1.7 SCK(在系統(tǒng)編程用) </p><p> P2 口:P2 口是一個具有內部上拉電阻的8 位雙向I/O 口,P2 輸出緩沖器能驅動 。4 個 TTL 邏輯電平。對P2 端口寫“1”時,內部上拉電阻把端口拉高,此時可以作為輸入 口使用。作為輸入使用時,被外部拉低的引腳由于內部電阻的原因,將輸出電流(
23、IIL)。 在訪問外部程序存儲器或用16位地址讀取外部數(shù)據(jù)存儲器(例如執(zhí)行MOVX @DPTR) 時,P2 口送出高八位地址。在這種應用中,P2 口使用很強的內部上拉發(fā)送1。在使用 8位地址(如MOVX @RI)訪問外部數(shù)據(jù)存儲器時,P2口輸出P2鎖存器的內容。 在flash編程和校驗時,P2口也接收高8位地址字節(jié)和一些控制信號。 </p><p> P3 口:P3 口是一個具有內部上拉電阻的8 位雙向I/O
24、口,p3 輸出緩沖器能驅動4 個 TTL 邏輯電平。對P3 端口寫“1”時,內部上拉電阻把端口拉高,此時可以作為輸入 口使用。作為輸入使用時,被外部拉低的引腳由于內部電阻的原因,將輸出電流(IIL)。 P3口亦作為AT89S52特殊功能(第二功能)使用,如下表所示。 在flash編程和校驗時,P3口也接收一些控制信號。 </p><p> 端口引腳 第二功能: </p><p> P3
25、.0 RXD(串行輸入口) </p><p> P3.1 TXD(串行輸出口) </p><p> P3.2 INTO(外中斷0) </p><p> P3.3 INT1(外中斷1) </p><p> P3.4 TO(定時/計數(shù)器0) </p><p> P3.5 T1(定時/計數(shù)器1) </p>
26、;<p> P3.6 WR(外部數(shù)據(jù)存儲器寫選通) </p><p> P3.7 RD(外部數(shù)據(jù)存儲器讀選通) </p><p> 此外,P3口還接收一些用于FLASH閃存編程和程序校驗的控制信號。 </p><p> RST:復位輸入。當振蕩器工作時,RST引腳出現(xiàn)兩個機器周期以上高電平將是單片機復位。 </p><p&g
27、t; ALE/PROG:當訪問外部程序存儲器或數(shù)據(jù)存儲器時,ALE(地址鎖存允許)輸出脈沖用于鎖存地址的低8位字節(jié)。一般情況下,ALE仍以時鐘振蕩頻率的1/6輸出固定的脈沖信號,因此它可對外輸出時鐘或用于定時目的。要注意的是:每當訪問外部數(shù)據(jù)存儲器時將跳過一個ALE脈沖。對FLASH存儲器編程期間,該引腳還用于輸入編程脈沖(PROG)。如有必要,可通過對特殊功能寄存器(SFR)區(qū)中的8EH單元的D0位置位,可禁止ALE操作。該位置位后
28、,只有一條MOVX和MOVC指令才能將ALE激活。此外,該引腳會被微弱拉高,單片機執(zhí)行外部程序時,應設置ALE禁止位無效。 </p><p> PSEN:程序儲存允許(PSEN)輸出是外部程序存儲器的讀選通信號,當AT89S52由外部程序存儲器取指令(或數(shù)據(jù))時,每個機器周期兩次PSEN有效,即輸出兩個脈沖,在此期間,當訪問外部數(shù)據(jù)存儲器,將跳過兩次PSEN信號。 </p><p>
29、EA/VPP:外部訪問允許,欲使CPU僅訪問外部程序存儲器(地址為0000H-FFFFH),EA端必須保持低電平(接地)。需注意的是:如果加密位LB1被編程,復位時內部會鎖存EA端狀態(tài)。如EA端為高電平(接Vcc端),CPU則執(zhí)行內部程序存儲器的指令。FLASH存儲器編程時,該引腳加上+12V的編程允許電源Vpp,當然這必須是該器件是使用12V編程電壓Vpp。 </p><p> XTAL1:振蕩器反相放大器和
30、內部時鐘發(fā)生電路的輸入端。 </p><p> XTAL2:振蕩器反相放大器的輸出端。</p><p> 2.12 音樂播放部分</p><p> 樂音實際上是固定周期的信號。本系統(tǒng)是用AT89s52 的定時器控制,在P3.6腳上輸出方波周期信號,產(chǎn)生音樂。樂曲中,每一音符對應著確定的頻率,我們將每一音符的時間常數(shù)和其相應的節(jié)拍常數(shù)作為一組,按順序將樂曲中的所
31、有常數(shù)排列成一個表,然后由查表程序依次取出,產(chǎn)生音符并控制節(jié)奏,就可以實現(xiàn)演奏效果。在輸出中我們用蜂鳴器及其驅動電路實現(xiàn)發(fā)聲。</p><p> 2.13電子琴彈奏部分</p><p> 本系統(tǒng)設置了10個按鍵,其中三個按鍵為高音、中音、低音的選擇按鍵,其余為發(fā)音按鍵,按下不同的按鍵產(chǎn)生不同的音符,通過按鍵時間的長短控制發(fā)音的長短,這樣彈奏人員可以隨心所欲的彈奏自己所喜愛的樂曲。電子琴
32、彈奏實際上就是把每個按鍵所對應的值經(jīng)過處理后發(fā)給單片機,再在單片機內把數(shù)字當作指針指向所對應的音符。我們運用單片機的最小系統(tǒng),用P2口的低三位作高音、中音、低音的選擇按鍵的接口,用P1口的低七位作發(fā)音按鍵的接口。 </p><p> 2.2 具體發(fā)音原理</p><p> 一首音樂是許多不同的音階組成的,而每個音階對應著不同的頻率,這樣我們就可以利用不同的頻率的組合,即可構成我們所想
33、要的音樂了,當然對于單片機來產(chǎn)生不同的頻率非常方便,我們可以利用單片機的定時/計數(shù)器T0來產(chǎn)生這樣方波頻率信號,因此,我們只要把各個音階對應頻率關系弄正確即可。</p><p> 若要產(chǎn)生音頻脈沖,只要算出某一音頻的周期(1/頻率),再將此周期除以2,即為半周期的時間。利用定時器計時半周期時間,每當計時終止后就將蜂鳴器端口反相,然后重復計時再反相。就可在該引腳上得到此頻率的脈沖實現(xiàn)發(fā)音。</p>
34、<p> 利用AT89S52的內部定時器使其工作計數(shù)器模式(MODE1)下,改變計數(shù)初值TH0及TL0以產(chǎn)生不同頻率的方法產(chǎn)生不同音階,例如,頻率為523Hz,其周期T=1/523=1912μs,因此只要令計數(shù)器計時956μs/1μs=956,每計數(shù)956次時將I/O反相,就可得到中音DO(523Hz)。</p><p> 計數(shù)脈沖值與頻率的關系式是:</p><p> N
35、=fi÷2÷fr </p><p> 式中,N是計數(shù)值;fi是機器頻率(晶體振蕩器為12MHz時,其頻率為1MHz);fr是想要產(chǎn)生的頻率。</p><p> 其計數(shù)初值T的求法如下:</p><p> T=65536-N=65536-fi÷2÷fr</p><p> 例如:設K=65536,f
36、i=1MHz,求低音DO(261Hz)、中音DO(523Hz)、高音DO(1046Hz)的計數(shù)值。</p><p> T=65536-N=65536-fi÷2÷fr</p><p> ?。?5536-1000000÷2÷fr=65536-500000/fr</p><p> 低音DO的T=65536-500000/262=
37、63628</p><p> 中音DO的T=65536-500000/523=64580</p><p> 高音DO的T=65536-500000/1046=65058</p><p> 當播放音樂時,除了考慮音頻外,還要考慮到音樂的音拍。本系統(tǒng)中,用軟件延時來控制發(fā)音時間的長短,控制節(jié)拍。下表是各調1/4節(jié)拍的時間表。</p><p>
38、;<b> 2.3各部分電路</b></p><p><b> 2.31晶振</b></p><p><b> 復位電路</b></p><p><b> 2.33按鍵</b></p><p><b> 2.34 發(fā)音</b&g
39、t;</p><p><b> 3 軟件設計</b></p><p><b> 3.1流程圖</b></p><p><b> 3.2 主程序代碼</b></p><p> 見附錄一 源程序代碼</p><p> 4、Proteus軟件仿真&l
40、t;/p><p><b> 見附錄2 仿真圖</b></p><p><b> 5 課程設計體會</b></p><p> 通過此次課程設計,使我更加扎實的掌握了有關單片機方面的知識,在設計過程中雖然遇到了一些問題,但經(jīng)過一次又一次的思考,一遍又一遍的檢查終于找出了原因所在,也暴露出了前期我在這方面的知識欠缺和經(jīng)驗不足。
41、實踐出真知,通過親自動手制作,使我們掌握的知識不再是紙上談兵。</p><p> 過而能改,善莫大焉。在課程設計過程中,我們不斷發(fā)現(xiàn)錯誤,不斷改正,不斷領悟,不斷獲取。最終的檢測調試環(huán)節(jié),本身就是在踐行“過而能改,善莫大焉”的知行觀。這次課程設計終于順利完成了,在設計中遇到了很多問題,最后在老師的指導下,終于游逆而解。在今后社會的發(fā)展和學習實踐過程中,一定要不懈努力,不能遇到問題就想到要退縮,一定要不厭其煩的發(fā)
42、現(xiàn)問題所在,然后一一進行解決,只有這樣,才能成功的做成想做的事,才能在今后的道路上劈荊斬棘,而不是知難而退,那樣永遠不可能收獲成功,收獲喜悅,也永遠不可能得到社會及他人對你的認可!</p><p> 課程設計誠然是一門專業(yè)課,給我很多專業(yè)知識以及專業(yè)技能上的提升,同時又是一門講道課,一門辯思課,給了我許多道,給了我很多思,給了我莫大的空間。同時,設計讓我感觸很深。使我對抽象的理論有了具體的認識。通過這次課程設計
43、,我掌握了PROTUES、WAVE6000等軟件,用WAVE6000進行程序的編譯,用PROTUES進行軟硬件系統(tǒng)的仿真。</p><p> 回顧起此課程設計,至今我仍感慨頗多,從理論到實踐,在這段日子里,可以說得是苦多于甜,但是可以學到很多很多的東西,同時不僅可以鞏固了以前所學過的知識,而且學到了很多在書本上所沒有學到過的知識。通過這次課程設計使我懂得了理論與實際相結合是很重要的,只有理論知識是遠遠不夠的,只
44、有把所學的理論知識與實踐相結合起來,從理論中得出結論,才能真正為社會服務,從而提高自己的實際動手能力和獨立思考的能力。在設計的過程中遇到問題,可以說得是困難重重,但可喜的是最終都得到了解決。</p><p><b> 參考文獻</b></p><p> [1] 余發(fā)山,王福忠.單片機原理及應用技術.徐州:中國礦業(yè)大學出版社,2008年</p><
45、;p> [2] 韓志軍等.單片機應用系統(tǒng)設計.北京:機械工業(yè)出版社,2004.75-83</p><p> [3] 王守中.51單片機開發(fā)入門與典型實例.北京:人民郵電出版社,2007.139-149</p><p> [4] 周潤景等. Proteus在MCS-51&ARM7系統(tǒng)中的應用百例.北京:電子工業(yè)出版社,2006.132-139</p><
46、;p> [5] 王為青,邱文勛.51單片機應用開發(fā)案例精選.北京:人民郵電出版社,2007.61-65</p><p><b> 附錄1 源程序代碼</b></p><p> #include <reg52.h></p><p> #include <intrins.h></p><p&
47、gt; #define SYSTEM_OSC 12000000//定義晶振頻率12000000HZ</p><p> #define SOUND_SPACE 4/5 //定義普通音符演奏的長度分率,//每4分音符間隔</p><p> #define uchar unsigned char</p><p> #define uint unsign
48、ed int</p><p> #define P_key P1</p><p> sbit beep=P3^6;//蜂鳴器控制端口P1^0!</p><p> Unsigned int code sy[21]={194,173,154,145,129,115,102,390,347,309,291,260,231,205,96, 86, 76, 72,
49、 64, 56, 50};</p><p> unsigned int code FreTab[12]= { 262,277,294,311,330,349,369,392,415,440,466,494 }; //原始頻率表</p><p> unsigned char code SignTab[7] = { 0,2,4,5,7,9,11 }; //1~7在頻率表中的位置<
50、;/p><p> unsigned char code LengthTab[7]= { 1,2,4,8,16,32,64 }; </p><p> unsigned char Sound_Temp_TH0,Sound_Temp_TL0;//音符定時器初值暫存 </p><p> unsigned char Sound_Temp_TH1,Sound_Temp
51、_TL1;//音長定時器初值暫存</p><p> //曲譜存貯格式 unsigned char code MusicName{音高,音長,音高,音長...., 0,0};末尾:0,0 表示結束(Important)</p><p> unsigned char code Music_Girl[]={ </p><p> 25,3,25,14,26,4,3
52、1,103,27,4,26,3,23,14,22,4,21,2,23,3,32,3,32,14,27,4,26,14,23,4,25,12,25,2,25,3,25,14,26,4,31,103,27,4,26,3,25,14,26,4,23,2,16,3,26,3,26,14,25,4,25,14,23,4,22,12,22,2,23,3,23,14,22,4,25,3,25,4,23,4,22,3,23,14,22,4,21,103
53、,22,4,23,103,25,4,27,14,26,4,25,3,26,12,26,2,31,3,31,14,26,4,31,103,31,4,26,13,25,14,23,4,22,2,16,3,26,3,25,14,23,4,23,14,22,4,21,102,31,14,32,4,33,4,33,3,33,4,32,3,33,14,32,4,31,102,26,14,31,4,32,4,32,3,33,4,32,14,27,4,
54、26,15,27,15,26,5,25,12,25,2,26,14,31,4,26,4</p><p><b> };</b></p><p> void delay_us(uint i);//us級延時程序延時y(us) = 9.75*i + 17.44!</p><p> void delay_ms(uint t);//毫秒級
55、延時函數(shù)!</p><p> void didi(uint k,uint t1,uint t2);//蜂鳴器進行響t1靜t2的k次動作!</p><p> void keyscan(void);//按鍵掃描動作!</p><p> void yindiao(uint i);//產(chǎn)生不同頻率聲音的函數(shù)!</p><p> void
56、 music(uchar diao);//按鍵音優(yōu)化!</p><p> void InitialSound(void);//自動播放需要的定時器設置等!</p><p> void Play(unsigned char *Sound,unsigned char Signature,unsigned Octachord,unsigned int Speed);</p>
57、<p> void BeepTimer0(void);//音符發(fā)生中斷//自動播放函數(shù)!</p><p> void main()</p><p><b> {</b></p><p> didi(2,100,40);//兩聲提示!</p><p> keyscan();</p&
58、gt;<p><b> }</b></p><p> void delay_us(uint i)</p><p> { while(i--);//us級延時程序延時y(us) = 9.75*i + 17.44!</p><p><b> }</b></p><p>
59、void delay_ms(uint t)//毫秒級延時函數(shù)!</p><p><b> {</b></p><p><b> uint i,j;</b></p><p> for(j=0;j<t;j++)</p><p> for(i=0;i<110;i++);</p&
60、gt;<p><b> }</b></p><p> void didi(uint k,uint t1,uint t2)//蜂鳴器進行響t1靜t2的k次動作!</p><p><b> {</b></p><p><b> uint i;</b></p><p
61、> for(i=0;i<k;i++)</p><p><b> {</b></p><p><b> beep=0;</b></p><p> delay_ms(t1);</p><p><b> beep=1;</b></p><p&
62、gt; delay_ms(t2);</p><p><b> }</b></p><p><b> }</b></p><p> void keyscan(void)//按鍵掃描動作!</p><p><b> {</b></p><p>
63、 uchar tiaozheng=0;</p><p><b> while(1)</b></p><p><b> {</b></p><p> if((P2&0x01)==0x00)</p><p><b> {</b></p><p&g
64、t; InitialSound();</p><p> didi(2,80,40);</p><p> InitialSound();</p><p> Play(Music_Girl,0,3,200);//Play(樂曲名,調號,升降八度,演奏速度);</p><p><b> }</b></p>
65、<p> else if((P_key&0xff)!=0xff)//此處內部括號不能少,否則不能進入下面。</p><p><b> {</b></p><p> if((P2&0x04)==0)//0100 0000當前H也按下了!</p><p><b> {</b><
66、;/p><p> tiaozheng=14;//進入高音區(qū)!</p><p> if(P_key==0xfd){music(tiaozheng+0);} //1111 1101</p><p> if(P_key==0xfb){music(tiaozheng+1);} //1111 1011</p><p> if(P_key==0x
67、f7){music(tiaozheng+2);}</p><p> if(P_key==0xef){music(tiaozheng+3);}</p><p> if(P_key==0xdf){music(tiaozheng+4);}</p><p> if(P_key==0xbf){music(tiaozheng+5);}</p><p&g
68、t; if(P_key==0x7f){music(tiaozheng+6);}</p><p><b> }</b></p><p> else if((P2&0x02)==0)//1000 0000當前L也按下了!</p><p><b> {</b></p><p> tia
69、ozheng=7;//進入低音區(qū)!</p><p> if(P_key==0xfd){music(tiaozheng+0);}</p><p> if(P_key==0xfb){music(tiaozheng+1);}</p><p> if(P_key==0xf7){music(tiaozheng+2);}</p><p> i
70、f(P_key==0xef){music(tiaozheng+3);}</p><p> if(P_key==0xdf){music(tiaozheng+4);}</p><p> if(P_key==0xbf){music(tiaozheng+5);}</p><p> if(P_key==0x7f){music(tiaozheng+6);} </p&
71、gt;<p><b> }</b></p><p> else//是默認的中音!</p><p><b> {</b></p><p> tiaozheng=0;</p><p> if(P_key==0xfd){music(tiaozheng+0);</p>
72、<p> if(P_key==0xfb){music(tiaozheng+1);}</p><p> if(P_key==0xf7){music(tiaozheng+2);}</p><p> if(P_key==0xef){music(tiaozheng+3);}</p><p> if(P_key==0xdf){music(tiaozheng
73、+4);}</p><p> if(P_key==0xbf){music(tiaozheng+5);}</p><p> if(P_key==0x7f){music(tiaozheng+6);}</p><p><b> }</b></p><p><b> }</b></p>
74、<p><b> }</b></p><p><b> }</b></p><p> void yindiao(uint i)//產(chǎn)生不同頻率聲音的函數(shù)</p><p><b> {</b></p><p><b> beep=0;</
75、b></p><p> delay_us(i);</p><p><b> beep=1;</b></p><p> delay_us(i);</p><p><b> }</b></p><p> void music(uchar diao)//按鍵音
76、優(yōu)化!</p><p><b> {</b></p><p> uint i=0,jizhun=20;</p><p> switch(diao)</p><p><b> {</b></p><p> case 0:for(i=0;i<(jizhun+(5
77、*diao));i++)yindiao(sy[diao]);break;</p><p> case 1:for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break;</p><p> case 2:for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break;<
78、/p><p> case 3:for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break;</p><p> case 4:for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break;</p><p> case 5:for(i=0;i<
79、(jizhun+(5*diao));i++)yindiao(sy[diao]);break;</p><p> case 6:for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break;</p><p> case 7:for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);
80、break;</p><p> case 8:for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break;</p><p> case 9:for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break;</p><p> case 10:fo
81、r(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break;</p><p> case 11:for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break;</p><p> case 12:for(i=0;i<(jizhun+(5*diao));i++)yindi
82、ao(sy[diao]);break;</p><p> case 13:for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break;</p><p> case 14:for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break;</p><p&g
83、t; case 15:for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break;</p><p> case 16:for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break;</p><p> case 17:for(i=0;i<(jizhun+(5*d
84、iao));i++)yindiao(sy[diao]);break;</p><p> case 18:for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break;</p><p> case 19:for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break;<
85、/p><p> case 20:for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break;</p><p> default:break;</p><p><b> }</b></p><p><b> }</b></
86、p><p> void InitialSound(void)//自動播放需要的定時器設置等!</p><p><b> {</b></p><p><b> beep = 1;</b></p><p> Sound_Temp_TH1 = (65535-(1/1200)*SYSTEM_OSC)
87、/256;// 計算TL1應裝入的初值 (10ms的初裝值)</p><p> Sound_Temp_TL1 = (65535-(1/1200)*SYSTEM_OSC)%256;// 計算TH1應裝入的初值 </p><p> TH1 = Sound_Temp_TH1;</p><p> TL1 = Sound_Temp_TL1;</p>
88、<p> TMOD |= 0x11;//定時器0和定時器1都是方式1 16位計數(shù)。</p><p> ET0 = 1;</p><p> ET1 = 0;</p><p> TR0 = 0;</p><p> TR1 = 0;</p><p><b> IT0=
89、0;</b></p><p><b> EX0=1;</b></p><p> EA = 1;</p><p> }//曲譜存貯格式 unsigned char code MusicName{音高,音長,音高,音長...., 0,0};末尾:0,0 表示結束(Important)</p><p&g
90、t; void Play(unsigned char *Sound,unsigned char Signature,unsigned Octachord,unsigned int Speed)</p><p><b> {</b></p><p> unsigned int NewFreTab[12];//新的頻率表</p><p>
91、 unsigned char i,j;</p><p> unsigned int Point,LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;</p><p> unsigned char Tone,Length,SL,SH,SM,SLen,XG,FD;</p><p> for(i=0
92、;i<12;i++) // 根據(jù)調號及升降八度來生成新的頻率表 </p><p><b> {</b></p><p> j = i + Signature;</p><p> if(j > 11)//進入高音音域!</p><p><b> {</b><
93、/p><p><b> j = j-12;</b></p><p> NewFreTab[i] = FreTab[j]*2;</p><p><b> }</b></p><p><b> else</b></p><p> NewFreTab[i
94、] = FreTab[j];</p><p> if(Octachord == 1)//需要降八度!</p><p> NewFreTab[i]>>=2;</p><p> else if(Octachord == 3)//需要升八度!</p><p> NewFreTab[i]<<=2;
95、 //否則不用改!</p><p> }</p><p> SoundLength = 0;</p><p> while(Sound[SoundLength] != 0x00)//計算歌曲長度</p><p><b> {</b></p><p> Sou
96、ndLength+=2;</p><p><b> }</b></p><p> Point = 0;</p><p> Tone = Sound[Point]; //讀出音調!</p><p> Length = Sound[Point+1]; // 讀出第一個音符和它時時值!</p&g
97、t;<p> LDiv0 = 12000/Speed;// 算出1分音符的長度(幾個10ms) LDiv4 = LDiv0/4; // 算出4分音符的長度 </p><p> LDiv4 = LDiv4-LDiv4*SOUND_SPACE; // 普通音最長間隔標準 </p><p> TR0 = 0;</p><p&
98、gt; TR1 = 1;</p><p> while(Point < SoundLength)</p><p><b> {</b></p><p> SL=Tone%10; //計算出音符 </p><p> SM=Tone/10%10; //計算出高低音 <
99、/p><p> SH=Tone/100; //計算出是否升半 </p><p> CurrentFre = NewFreTab[SignTab[SL-1]+SH]; //查出對應音符的頻率 </p><p><b> if(SL!=0)</b></p><p><b> {</b&
100、gt;</p><p> if (SM==1) CurrentFre >>= 2; //低音 </p><p> if (SM==3) CurrentFre <<= 2; //高音</p><p> Temp_T = 65536-(50000/CurrentFre)*10/(12000000/SYSTEM_OSC);//計算計數(shù)
101、器初值</p><p> Sound_Temp_TH0 = Temp_T/256; </p><p> Sound_Temp_TL0 = Temp_T%256; </p><p> TH0 = Sound_Temp_TH0; </p><p> TL0 = Sound_Temp_TL0 + 12; //加12是對中斷延時的補償 &l
102、t;/p><p><b> }</b></p><p> SLen=LengthTab[Length%10]; //算出是幾分音符</p><p> XG=Length/10%10; //算出音符類型(0普通1連音2頓音) </p><p> FD=Length/100;</p><p&g
103、t; LDiv=LDiv0/SLen; //算出連音音符演奏的長度(多少個10ms)</p><p> if (FD==1) //有浮點,加半個時值!</p><p> LDiv=LDiv+LDiv/2;</p><p> if(XG!=1)</p><p> if(XG==0) //算出普通音符的演奏長度
104、 </p><p> if (SLen<=4)</p><p> LDiv1=LDiv-LDiv4;</p><p><b> else</b></p><p> LDiv1=LDiv*SOUND_SPACE;</p><p><b> else</b>&l
105、t;/p><p> LDiv1=LDiv/2;//算出頓音的演奏長度 </p><p><b> else</b></p><p> LDiv1=LDiv;</p><p> if(SL==0) LDiv1=0;</p><p> LDiv2=LDiv-LDiv1; //算出不發(fā)音的長
106、度 </p><p> if (SL!=0)</p><p> { TR0=1;</p><p> for(i=LDiv1;i>0;i--) //發(fā)規(guī)定長度的音 </p><p> { while(TF1==0);</p><p> TH1 = Sound_Temp_TH1;</p&g
107、t;<p> TL1 = Sound_Temp_TL1;</p><p><b> TF1=0;</b></p><p><b> }</b></p><p><b> }</b></p><p> if(LDiv2!=0)</p><
108、;p> { TR0=0; beep=1;</p><p> for(i=LDiv2;i>0;i--) //音符間的間隔</p><p> { while(TF1==0);</p><p> TH1 = Sound_Temp_TH1;</p><p> TL1 = Sound_Temp_TL1;</p&g
109、t;<p><b> TF1=0;</b></p><p><b> }</b></p><p><b> }</b></p><p> if((P1&0xff)!=0xff)</p><p><b> break;</b>
110、</p><p> Point+=2; </p><p> Tone=Sound[Point];</p><p> Length=Sound[Point+1];</p><p><b> }</b></p><p><b> beep = 1;</b></p&
111、gt;<p><b> }</b></p><p> void BeepTimer0(void) interrupt 1//音符發(fā)生中斷</p><p><b> {</b></p><p> beep = !beep;</p><p> TH0 = Sound_Te
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
評論
0/150
提交評論