單片機課程設計單片機演奏樂曲試驗_第1頁
單片機課程設計單片機演奏樂曲試驗_第2頁
單片機課程設計單片機演奏樂曲試驗_第3頁
單片機課程設計單片機演奏樂曲試驗_第4頁
單片機課程設計單片機演奏樂曲試驗_第5頁
已閱讀5頁,還剩14頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

1、單片機課程設計課程設計題目:單片機演奏樂曲試驗課程設計組: 08電子信息工程姓名: 單片機演奏樂曲實驗摘要:本文是應用16f877a單片機原理和控制理論來設計音樂盒的硬件電路,并利用16單片機語言進行程序設計。通過控制單片機內(nèi)部的定時器來產(chǎn)生不同頻率的方波,驅動喇叭發(fā)出不同音調的音樂,再利用延遲來控制發(fā)音時間的長短。該程序通過把樂譜轉化成相應的定時常數(shù)來驅動發(fā)音設備演奏出悅耳動聽的音樂。這種控制電路結構簡單,可靠性高,應用性強;軟件程序適應范圍廣,對于不同的音樂只需要改變相應的定時常數(shù)即可。關鍵詞:16f877a單片機 匯編語言單片機控制電路的設計本設計中用到了16f877a單片機,蜂鳴器。蜂

2、鳴器硬件電路控制如下圖音樂產(chǎn)生的方法:一首音樂是許多不同的音階組成的,而每個音階對應著不同的頻率,這樣我們就可以利用不同的頻率的組合,即可構成我們所想要的音樂了,當然對于單片機來產(chǎn)生不同的頻率非常方便,我們可以利用單片機的定時/計數(shù)器t0來產(chǎn)生這樣方波頻率信號,因此,我們只要把一首歌曲的音階對應頻率關系弄正確即可?,F(xiàn)在以單片機12mhz晶振為例,例出高中低音符與單片機計數(shù)t0相關的計數(shù)值如下表4.1所示:表4.1高中低音符與單片機計數(shù)t0相關的計數(shù)值音符對應的pr2值音符對應的pr2值m_1119m_2105m_394m_579m_670h_159l_5158l_6141如表4.2所示:音樂的

3、音拍,一個節(jié)拍為單位(c調)表4.2音樂的音拍曲調值delay曲調值delay調4/4125ms調4/462ms調3/4187ms調3/494ms調2/4250ms調2/4125ms對于不同的曲調我們也可以用單片機的另外一個定時/計數(shù)器來完成。發(fā)音部分代碼在程序中實現(xiàn),靠單片機的一個管腳輸出,考慮到聲音可能不夠大所以我們加入了功放電路,利用lm386來對聲音信號進行放大。音頻輸出信號由adu out引出,信號可經(jīng)功放電路lm386輸出到揚聲器或耳機。軟件流程圖程序代碼如下所示:;樂曲名:友誼天長地久*;文件名“3.asm”;功能:單片機演奏樂曲實驗;*#include p16f877a.inc

4、 #define youyi 0x2100;樂譜編號#define l_5.158#definel_6.141#definem_1.119#definem_2.105#definem_3.94#definem_5.79#definem_6.70#defineh_1.59#definem_0.0; tone8=158,141,119,105,94,79,70,59;聲調的高低,實際上是pwm的周期值;計算方法是ccp的時鐘1mhz除以預分頻比16,再除以要產(chǎn)生的頻率,最后再減去1。portd_d equ 20h ;顯示緩沖器countcount1 equ 21hcount2 equ 22hcou

5、nt3 equ 23hcount4 equ 24hsavew equ 25h ;w保護寄存器saves equ 26h ;status保護寄存器count5 equ 27h ;節(jié)拍數(shù)h equ 28h ;地址寄存器hang equ 29h ;行寄存器lie equ 30h ;列寄存器tmp1 equ 31h ;tmp1緩存寄存器byte equ 32h ;緩存count6 equ 33h ;節(jié)拍數(shù)count7 equ 34h ;節(jié)拍數(shù)dd_ram_addrequ 35h ; 第一行顯示地址寄存器dd_ram_ul equ 36h ; 第二行顯示地址寄存器count equ 37hcount e

6、qu 38h ;計數(shù)寄存器count2 equ 39h;*;* 定義 lcd數(shù)據(jù)& 控制i/o口 ;*#definelcd_db7 portb,3 ;占用的i/o口定義 #definelcd_db6 portb,2 ;lcd的db6與rb2連接,其它類推#definelcd_db5 portb,1 ;#definelcd_db4 portb,0 ;#define lcd_en portc,0#define lcd_rs portc,1#definelcd_db7_dirtrisb,3 ;對應的方向寄存器定義#definelcd_db6_dirtrisb,2 ;#definelcd_db5_di

7、rtrisb,1 ;#definelcd_db4_dirtrisb,0 ;#definelcd_en_dirtrisc,0 ;#definelcd_rs_dirtrisc,1 ; ;*lcd 模塊命令*#definedisp_on0x00c ; 開顯示#definedisp_on_c0x00e ; 開顯示, 開指針#definedisp_on_b0x00f ; 開顯示, 開指針,開閃爍#definedisp_off0x008 ; 關顯示#defineclr_disp0x001 ; 清顯示的操作數(shù)#defineentry_inc0x006 ; 操作數(shù)#defineentry_inc_s0x007

8、 ; 操作數(shù)#defineentry_dec0x004 ; 操作數(shù)#defineentry_dec_s0x005 ; 操作數(shù);* org youyi de l_5,l_5,m_1,m_1,m_1,m_1,m_1,m_1,m_1,m_3,m_3,m_2,m_2,m_2,m_2de m_1,m_2,m_2,m_3,m_3,m_1,m_1,m_1,m_1,m_1,m_3,m_3,m_5,m_5,m_6de m_6,m_6,m_6,m_6,m_6,m_6,m_6,m_6,m_6,m_5,m_5,m_5,m_5,m_3,m_3de m_3,m_1,m_1,m_2,m_2,m_2,m_2,m_1,m_2,

9、m_2,m_3,m_3,m_1,m_1,m_1de m_1,l_6,l_6,l_6,l_5,l_5,m_1,m_1,m_1,m_1,m_1,m_1,m_1,m_1,m_6de m_6,m_5,m_5,m_5,m_5,m_3,m_3,m_3,m_1,m_1,m_2,m_2,m_2,m_2,m_1de m_2,m_2,m_6,m_6,m_5,m_5,m_5,m_5,m_3,m_3,m_3,m_5,m_5,m_6,m_6de m_6,m_6,m_6,m_6,m_6,m_6,h_1,h_1,m_5,m_5,m_5,m_5,m_3,m_3,m_3de m_1,m_1,m_2,m_2,m_2,m_2,m_

10、1,m_2,m_2,m_3,m_3,m_1,m_1,m_1,m_1de l_6,l_6,l_6,l_5,l_5,m_1,m_1,m_1,m_1,m_1,m_1,m_0,m_0,m_0,m_0;* org 0x000 nop ;空指令 goto main org 0x004 ;中斷入口 banksel savew movwf savew swapf status,w clrf status movwf saves ;中斷保護 goto ccpint ;*table*table1 ;取第一行的顯示碼tmr2 count addwf pcl,1 ;地址偏移量加當前pc值 retlw i ;t ret

11、lw n ;m retlw n ;r retlw o ;2 retlw v ;空格 retlw a ;空格 retlw t ;c retlw o ;o retlw r ;u retlw ;n retlw ;t retlw v ;n retlw 1 ;t retlw . ;n retlw 5 ;t retlw 00h;*table1*table ;取第二行顯示time: ms addwf pcl,1 ;地址偏移量加當前pc值 retlw h ;t retlw e ;i retlw l ;m retlw l ;e retlw o ;: retlw ;空格 retlw p ;空格 retlw i ;

12、空格 retlw c ;空格 retlw ! ;空格 retlw 00h;*table2*table2 addwf pcl,1 retlw 30h ;0 retlw 31h ;1 retlw 32h ;2 retlw 33h ;3 retlw 34h ;4 retlw 35h ;5 retlw 36h ;6 retlw 37h ;7 retlw 38h ;8 retlw 39h ;9;*主程序開始*main call lcd_dispay banksel trisd ;選擇體1 clrf trisd ;portd為輸出端口 movlw 07h ; movwf option_reg ;1:256

13、 banksel t1con clrf count5 movlw 30h ;分頻器為1:8,關閉tmr1 movwf t1con ; bcf pir1,tmr1if ;溢出標志位清零 clrf tmr1h clrf tmr1l movlw 0xee ;設定tmr1低位初值 addwf tmr1l ; movlw 0x85 ;設定tmr1高位初值 addwf tmr1h ; bsf t1con,0 ;啟動tmr1 banksel trisc ;跳到體1 bcf trisc,2 ;ccp1為輸出狀態(tài) banksel eeadr ;跳到體2 movlw youyi ;將地址存到w寄存器 movwf

14、eeadr ;將地址送入eeprom地址寄存器 banksel eecon1 ;選定bank3 bcf eecon1,eepgd ;選擇eeprom作為非易失性存儲器操作對象 bsf eecon1,rd ;啟動一次讀eeprom的操作 banksel eedata ;跳到體2 movf eedata,w ;由于eeprom的讀出操作花費的時間很短,此時eeprom banksel pr2 ;跳到體1 movwf pr2 ;將w的值存到pr2 banksel t2con ;跳到體0 movlw 0x07 ;預分頻1:16,后預分頻1:1 movwf t2con ;開定時器2 movlw 0x0c

15、 ;將0x0c存到w寄存器 movwf ccp1con ;使用8位pwm方式 banksel pr2 ;跳到體1 movf pr2,0 ;將pr2值存到w寄存器 banksel ccpr1l ;跳到體0 movwf ccpr1l ;將w存到ccpr1l movlw b11111100 ;屏蔽低兩位 andwf ccpr1l,1 rrf ccpr1l,1 ;ccpr1l右移一位 rrf ccpr1l,1 ;ccpr1l右移一位 rrf ccpr1l,1 ;ccpr1l右移一位 banksel pie1 ;跳到體1 bsf pie1,tmr1ie ;啟動tmr1中斷 bsf intcon,peie

16、 ;開啟外設中斷 bsf intcon,gie ;開啟全局中斷 banksel portd ;選擇體0 clrf portd movlw 01h ;顯示緩沖器賦初值 movwf portd_d loop ;call delay_500ms ;延時500ms ;rlf portd_d ;顯示緩沖器循環(huán)左移 goto loop ;等待中斷;*ccpint中斷子程序*ccpint btfss pir1,tmr1if ;判斷是否是tmr1中斷 goto jmp4 ;否,跳出中斷 bcf pir1,tmr1if ;是,清中斷標志位 movlw 30h ;分頻器為1:8,關閉tmr1 movwf t1co

17、n ; clrf tmr1h ;清tmr1h clrf tmr1l ;清tmr1l movlw 0xee ;設定tmr1低位初值 addwf tmr1l ; movlw 0x85 ;設定tmr1高位初值 addwf tmr1h ; bsf t1con,0 ;啟動tmr1 banksel eeadr ;跳到體2 movlw youyi ;將地址存到w寄存器 movwf eeadr ;將地址送入eeprom地址寄存器 banksel count5 ;跳到體0 movf count5,0 ;將count存到w寄存器 banksel eeadr ;跳到體2 addwf eeadr,1 ;eeadr=e

18、eadr+count banksel eecon1 ;選定bank3 bcf eecon1,eepgd ;選擇eeprom作為非易失性存儲器操作對象 bsf eecon1,rd ;啟動一次讀eeprom的操作 banksel eedata ;跳到體2 movf eedata,w ;由于eeprom的讀出操作花費的時間很短,此時eeprom banksel pr2 ;跳到體1 movwf pr2 ;將w存到pr2 banksel ccpr1l ;跳到體0 movwf ccpr1l ;將w存到ccpr1l movlw b11111100 ;將11111100存到w寄存器 andwf ccpr1l,

19、1 ;屏蔽低兩位 rrf ccpr1l,1 ;ccpr1l左移一位 rrf ccpr1l,1 ;ccpr1l左移一位 rrf ccpr1l,1 ;ccpr1l右移一位 movlw .149 ;將149存到w寄存器 subwf count5,0 ;w=count-149 btfss status,c ;判斷是否有借位 goto jmp1 ;有,跳到jmp1 goto jmp2 ;無,跳到jmp2jmp1 incf count5,1 ;count=couint+1 goto jmp ;跳到jmpjmp2 clrf count5 ;count清零jmp movlw b00000000 ;送.0到w寄

20、存器 xorwf portd,0 ;判斷portd是否為0 btfss status,z goto jmp3 ;否,跳到jmp1 movf portd_d,0 ;是,將portd_d的值 movwf portd ;送到portd goto jmp4jmp3 clrf portd ;portd清零 bcf status,c ;清楚其他操作對c的影響 rlf portd_d ;顯示緩沖器循環(huán)左移 btfsc status,c goto jmp5 goto jmp4 jmp5 movlw 01h ;顯示緩沖器賦初值 movwf portd_d jmp4 swapf saves,w movwf sta

21、tus swapf savew,f swapf savew,w ;恢復中斷 retfie;*700ms延時子程序*delay_500ms movlw .5 movwf count3loop1 movlw d133 ;設置外部循環(huán)次數(shù) movwf count1 ;loop2 movlw d249 ;設置內(nèi)部循環(huán)次數(shù) movwf count2 ;loop3 decfsz count2 ,1 ;內(nèi)部循環(huán)變量自減1,為0則跳轉 goto loop3 ; decfsz count1,1 ;外部循環(huán)變量自減1,為0則跳轉 goto loop2 ; decfsz count3,1 ;外部循環(huán)變量自減1,為0

22、則跳轉 goto loop1 ; return ;返回主程序;*lcd_dispay顯示子程序*lcd_dispay banksel h ;選擇體0 movlw 0xc0 ;lcd第二行首地址 movwf dd_ram_ul movlw 0x80 ;lcd第一行首地址 movwf dd_ram_addr call lcd_intf ;調lcd初始化子程序 movlw .0 ;第一行顯示tmr2 count movwf hang ;的位置 movlw .2 movwf lie call adress ;調地址轉換子程序 call set_cursor ;調設置光標子程序 call display

23、 ;調第一行顯示子程序 movlw .1 ;第二行顯示time:xxxxms movwf hang ;的位置行和列 movlw .0 movwf lie call adress ;調地址轉換子程序 call set_cursor ;調設置光標子程序 call display1 ;調第二行顯示子程序 ;call watch_change ;調watch_change子程序 movlw .1 ;設置時間顯示位置行和列 movwf hang movlw .7 movwf lie call adress ;調地址轉換子程序 call set_cursor ;調設置光標子程序 ;call display

24、_watch ;調時間顯示子程序 return ;子程序返回;*lcd_intf初始化子程序* lcd_intf bsf status,rp0 ;bank 1 bcf status,rp1 ;初始化相關i/o引腳 bcf lcd_db7_dir bcf lcd_db6_dir bcf lcd_db5_dir bcf lcd_db4_dir bcf lcd_en_dir bcf lcd_rs_dir bcf status,rp0 ;bank 0 bcf lcd_rs bcf lcd_en ;清數(shù)據(jù)線 movlw0x28 ;設置工作方式 callsendcmd ;四位數(shù)據(jù)總線,兩行顯示,5x7點陣

25、字符 bsf lcd_en bcf lcd_en movlwdisp_on ;開顯示 callsendcmd movlwentry_inc ;設置指針移動方式 callsendcmd callclrlcd ;清屏 movlw 0x80 ;設定行值 call sendcmd return ;子程序返回;*adress地址轉換子程序*adress btfss hang,0 ;判斷行是否為1 goto j1 ;是,跳到j1 movf lie,0 ;否,將列值送到w寄存器 addwf dd_ram_ul,0 ;第二行首地址加上列值 goto j2j1 movf lie,0 ;將列值送到w寄存器 add

26、wf dd_ram_addr,0 ;第一行首地址加上列值 j2 movwf h ;將地址存到h寄存器 return ;子程序返回;*set_cursor設置光標位置子程序* set_cursor banksel h movf h,0 ;設置光標位置 call sendcmd movlw disp_on ; 開顯示 call sendcmd return ;子程序返回;*display第一行顯示子程序*display clrf count ;清0查表偏移地址 write_a movfw count ;count值送到w寄存器 call table ;查表,顯示tmr2 count movwf t

27、mp1 ;送暫存器 incf count,1 ;偏移地址加1 movfw tmp1 ;tmp1值送到w寄存器 xorlw 00h ;判斷是否顯示完所有數(shù)據(jù) btfsc status,z ;(約定表格做后一個00h做為結束標志) goto $+4 ;全部顯示完成 movfw tmp1 ;tmp1值送到w寄存器 call putclcd ;沒有顯示完,把當前查表所得數(shù)據(jù)送lcd顯示 goto write_a ;調用顯示程序 return ;子程序返回;*display1第二行顯示子程序*display1 clrf count ;清0查表偏移地址 write2_a movfw count ;coun

28、t值送到w寄存器 call table1 ;查表,顯示time: ms movwf tmp1 ;送暫存器 incf count,1 ;偏移地址加1 movfw tmp1 ;tmp1值送到w寄存器 xorlw 00h ;判斷是否顯示完所有數(shù)據(jù) btfsc status,z ;(約定表格做后一個00h做為結束標志) goto $+4 ;全部顯示完成 movfw tmp1 ;tmp1值送到w寄存器 call putclcd ;沒有顯示完,把當前查表所得數(shù)據(jù)送lcd顯示 goto write2_a ;調用顯示程序 return ;子程序返回;*putclcd 將字符數(shù)據(jù)送入 lcd * ;* 本程序將字符數(shù)據(jù)分成了高半字節(jié)和低半字節(jié)分別輸入 ;* 先送入的是高半字節(jié) ;* putclcd bsf lcd_rs ;設置為送數(shù)據(jù)模式 movwf byte call write ;寫

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論