PIC16F877A實現音樂播放程序(《兩只老虎》片段)
發布時間:2008年1月5日 2時7分
;PIC16F877A實現音樂播放程序(《兩只老虎》片段) ;功能說明: ;1.通過驅動實驗板上的蜂鳴器發聲,實現音樂的播放。 ;2.從TABLE中取出播放音樂的音調(1、2....7)通過改變該表中的值即可實現播放不同的音樂。 ;3.從TABLE_YP中取出播放音樂的音頻,即該音調持續的時間。 ;4.調整DELAY延時的長短即可實現音樂播放的快慢。 ;本實戰的目的是讓大家進一步熟悉 D單片機如何驅動蜂鳴器發聲。并通過改變持續發聲的時間長短來實現不同頻率的聲音。 ;硬件接法: ;1、蜂鳴器接RC6口。 ;2、本程序使用實驗板上的蜂鳴器發生發聲,撥碼開關13的第5位必須置1,其他碼開關都可以關閉。 ;本實例原提供者:pic16論壇會員 ppmy ,在此鳴謝ppmy同志共享本實例. ;由深圳市乾龍盛電子科技有限公司技術部鐘閨田(工程師)(論壇網名:zhongruntian)驗正并加于整理、注釋. ;網站:PIC單片機學習網 http://www.pic16.com 討論論壇:http://pic16.com/bbs/ ;版權所有,轉載請注明出處,并不能去掉或改變文件中的說明文字。 ;程序文件名“SONG.ASM" ;程序清單如下: ;*********************************** LIST P=PIC16F877,R=DEC #i nclude P16F877.INC ;*********************************** Errorlevel -302,-305 __CONFIG _DEBUG_OFF&_CP_ALL&_CPD_ON&_LVP_OFF&_BODEN_OFF&_PWRTE_ON&_WDT_OFF&_HS_OSC; ;***********************************寄存器定義 CBLOCK 0x20 JP YP L1 L2 TA:2 COUNT1 COUNT2 W_STACK ST_STACK ENDC ;************************************ ORG 0X0000 nop ;放置一條MCD所必須的空指令 GOTO MAIN ;主程序 ORG 0x0004 BTFSC PIR1,TMR1IF ;中斷子程序 GOTO T1 ;轉T1處理 RETFIE ORG 0x0010 ;************************************ MAIN CLRWDT ;喂狗 BCF STATUS,RP0 CLRF INTCON ;清除其他中斷標志位 CLRF PORTC CLRF PIR1 ;清除TMR1中斷標志位 BSF STATUS,RP0 BSF PIE1,0 ;使能TMR1中斷 MOVLW B'10111111' ;除RC6口輸出外,其他口都設為輸入 MOVWF TRISC BCF STATUS,RP0 MOVLW 0xC0 ;開啟中斷總允許位GIE跟PEIE MOVWF INTCON REPLAY CLRF COUNT1 ;從頭開始查表(亦即從頭開始唱歌) SING CLRF TMR1L CLRF TMR1H ;清零TMR1定器 MOVF COUNT1,0 CALL TABLE MOVWF COUNT2 ;暫存查表結果于COUNT2中 BCF STATUS,Z SUBLW 0x00 ;判斷是否查表到最后一個數值 BTFSC STATUS,Z GOTO REPLAY ;是,說明音樂播放完成,重頭開始播放 MOVF COUNT2,0 ANDLW 0x0F ;去掉高4位只保留低4位 MOVWF JP ;保存到JP中 SWAPF COUNT2,0 ;高低半字節交換 ANDLW 0x0F ;去掉高4位只保留低4位 MOVWF YP ;保存到YP中,這樣查表的結果的被分成高低半字節兩部分分別存放在YP跟JP中 DECF YP,1 MOVF YP,0 CALL TABLE_YP MOVWF TMR1H ;作為TMR1初值的高8位 MOVWF TA ;暫存TA中 INCF YP,0 CALL TABLE_YP MOVWF TMR1L ;作為TMR1初值的低8位 MOVWF TA+1 ;暫存TA+1中 BSF T1CON,TMR1ON ;開啟TMR1定時器 CALL DELAY ;延時一段時間 INCF COUNT1 ;COUNT1加1,以便查表得到下一個播放的音調 GOTO SING ;返回播放下一個音調 ;**************************延時程序 DELAY MOVLW 200 MOVWF L1 DELAY_1 MOVLW 225 MOVWF L2 DELAY_2 DECFSZ L2,1 GOTO DELAY_2 DECFSZ L1,1 GOTO DELAY_1 DECFSZ JP,1 GOTO DELAY CLRWDT RETURN ;*************************中斷現場保護 PUSH MOVWF W_STACK ;保存W的值 MOVF STATUS,0 MOVWF ST_STACK ;保存STATUS的值 RETURN ;************************中斷現場恢復 POP MOVF ST_STACK,0 MOVWF STATUS ;恢復STATUS的值 MOVF W_STACK,0 ;恢復W的值 RETURN ;************************中斷處理子程序 T1 CALL PUSH ;調用現場保護程序 MOVLW 0x40 ;RC6口輸出取反 XORWF PORTC,1 MOVF TA,0 MOVWF TMR1H MOVF TA+1,0 MOVWF TMR1L ;給TMR1賦初值 BSF T1CON,TMR1ON ;開啟定時器 BCF PIR1,TMR1IF ;清除標志位 CALL POP ;調用現場恢復程序 RETFIE TABLE_YP ADDWF PCL,1 RETLW 0xFC ;1 RETLW 0x44 RETLW 0xFC ;2 RETLW 0xAC RETLW 0xFD ;3 RETLW 0x09 RETLW 0xFD ;4 RETLW 0x34 RETLW 0xFD ;5 RETLW 0x82 RETLW 0xFD ;6 RETLW 0xC8 RETLW 0xFE ;7 RETLW 0x06 TABLE ADDWF PCL,1 RETLW 0x14 RETLW 0x34 RETLW 0x54 RETLW 0x14 RETLW 0x14 RETLW 0x34 RETLW 0x54 RETLW 0x14 RETLW 0x54 RETLW 0x74 RETLW 0x98 RETLW 0x54 RETLW 0x74 RETLW 0x98 RETLW 0x93 RETLW 0xB1 RETLW 0x93 RETLW 0x71 RETLW 0x54 RETLW 0x14 RETLW 0x93 RETLW 0xB1 RETLW 0x93 RETLW 0x71 RETLW 0x54 RETLW 0x14 RETLW 0x14 RETLW 0x94 RETLW 0x18 RETLW 0x14 RETLW 0x94 RETLW 0x18 RETLW 0x00 ;******************************************** end ;源程序結束 ;******************************************** ; 進入該實戰演練的工序流程如下: ; 1.創建源文件和編輯源文件;在此介紹一種不同于前面講的創建源文件的方法,用Windows附件中的”記事本” ; 這個為大家所熟知和好用的文件編輯器,并且可以方便的加入中文注釋.不過有兩點需要注意,一是注釋前面的 ; 分號”;”必須用西文半角輸入;二是必須用”.asm”擴展名存儲到事先建立的一個專用子目錄下. ; 2.打開MPLAB集成開發環境:首先在WINDOWS環境下,選用開始>程序>Microchip MPLAB>MPLAB命令,啟動MPLAB ; 并進入MPLAB的桌面. ; 3.創建項目:選用菜單File>New或Project>New Project,在事先建立的一個專用子目錄下創建一個新項目,將 ; 用記事本創建的源文件加入到該項目中. ; 4.建立項目中的目標文件:選擇菜單Project >Build All(項目>建立所有文件),MPLAB將自動調用MPASM將項目 ; 文件管理下的源文件(.asm)匯編成十六進制的目標文件(.hex).
OPTION_REG EQU 81H ; TRISA EQU 85H ;定義RA口方向控制寄存器 TRISB EQU 86H ;定義RB口方向控制寄存器 TRISC EQU 87H ;定義RC口方向控制寄存器 ADCON1 EQU 9FH ;定義ADC模塊控制寄存器1的地址 ;-----------------------STATUS C EQU 0 ;定義進位標志位位地址 Z EQU 2 ;定義0標志位位地址 RP0 EQU 5 ;寄存器體選 ;-------------------------INTCON T0IF EQU 2 ;定時器0溢出中斷標志位 T0IE EQU 5 ;定時器0溢出中斷允許/禁止 GIE EQU 7 ;總中斷允許/禁止 ;------------------------- RMT EQU 1 ;遙控接收輸入腳位地址(RA。1) ;------------------------- BITIN EQU 7 ;遙控接收數據位位標志 ;------------------------- CNT0 EQU 20H ;用戶臨時寄存器1 CNT1 EQU 21H ;用戶臨時寄存器2 CNT2 EQU 22H ;用戶臨時寄存器3 CNT3 EQU 23H ;用戶臨時寄存器4 TABADD EQU 24H ;數碼管顯示碼取碼用寄存器 FLAGS EQU 25H ;顯示位選標志位 DISPBUF_H EQU 26H ;顯示器高位 DISPBUF_L EQU 27H ;顯示器低位 W_TEMP EQU 2BH ;W現場保護寄存器 STATUS_TEMP EQU 2CH ;STATUS現場保護寄存器 CSR0 EQU 2DH ;遙控鍵碼反碼寄存器 CSR1 EQU 2EH ;遙控器鍵碼寄存器 CSR2 EQU 2FH ;遙控器用戶碼高8位寄存器 CSR3 EQU 30H ;遙控器用戶碼低8位寄存器 FLAGS2 EQU 31H ;臨時寄存器 CSR0A EQU 32H ;遙控接收32位數據暫存寄存器 CSR1A EQU 33H ;遙控接收32位數據暫存寄存器 CSR2A EQU 34H ;遙控接收32位數據暫存寄存器 CSR3A EQU 35H ;遙控接收32位數據暫存寄存器 ;-------------------- ORG 0000H NOP ;放置一條ICD必須的空操作指令 GOTO MAIN ORG 0004H GOTO TMR0SERV ;定時器中斷,掃描數碼管 ORG 0008H ;------------------------------------------------- CONVERT MOVWF PC ;將W寄存器內的7段顯示碼地址放入PC TABLE ;PC執行新地址指令, 跳到相對的地址執行? RETLW 0C0H ;0 ;RETLW指令,將七段顯示碼存入W后返回 RETLW 0F9H ;1 RETLW 0A4H ;2 RETLW 0B0H ;3 RETLW 099H ;4 RETLW 092H ;5 RETLW 082H ;6 RETLW 0F8H ;7 RETLW 080H ;8 RETLW 090H ;9 RETLW 088H ;A RETLW 083H ;b RETLW 0A7H ;c RETLW 0A1H ;d RETLW 086H ;E RETLW 08EH ;F ;----- ----------------------------------------------- TMR0SERV MOVWF W_TEMP ;現場保護 SWAPF STATUS,W ;用SWAPF才不會影響標志位 MOVWF STATUS_TEMP ;將W和STATUS存入各保護寄存器 MOVLW 0FFH MOVWF PORTC ;先熄滅所有數碼管以免閃爍 BSF PORTA,4 BSF PORTA,5 BSF PORTA,0 BSF PORTA,2 BSF PORTA,3 MOVLW TABLE MOVWF TABADD ;將轉換表的首地址存入TABADD MOVFW DISPBUF_L ;計數值(W)與轉換表的起始地址相加 BTFSS FLAGS,1 MOVFW DISPBUF_H ADDWF TABADD,W CALL CONVERT ;存入W后調用轉換表子程序 MOVWF PORTC ;送RC口顯示 BTFSS FLAGS,1 ;根據標志位選擇是點亮那一個數碼管 BCF PORTA,3 BTFSC FLAGS,1 BCF PORTA,2 COMF FLAGS,1 MOVLW .155 ;送定時器初值 MOVWF RTCC ;PIC16F877A實現音樂播放程序(《兩只老虎》片段) ;功能說明: ;1.通過驅動實驗板上的蜂鳴器發聲,實現音樂的播放。 ;2.從TABLE中取出播放音樂的音調(1、2....7)通過改變該表中的值即可實現播放不同的音樂。 ;3.從TABLE_YP中取出播放音樂的音頻,即該音調持續的時間。 ;4.調整DELAY延時的長短即可實現音樂播放的快慢。 ;本實戰的目的是讓大家進一步熟悉 D單片機如何驅動蜂鳴器發聲。并通過改變持續發聲的時間長短來實現不同頻率的聲音。 ;硬件接法: ;1、蜂鳴器接RC6口。 ;2、本程序使用實驗板上的蜂鳴器發生發聲,撥碼開關13的第5位必須置1,其他碼開關都可以關閉。 ;本實例原提供者:pic16論壇會員 ppmy ,在此鳴謝ppmy同志共享本實例. ;由深圳市乾龍盛電子科技有限公司技術部鐘閨田(工程師)(論壇網名:zhongruntian)驗正并加于整理、注釋. ;網站:PIC單片機學習網 http://www.pic16.com 討論論壇:http://pic16.com/bbs/ ;版權所有,轉載請注明出處,并不能去掉或改變文件中的說明文字。 ;程序文件名“SONG.ASM" ;程序清單如下: ;*********************************** LIST P=PIC16F877,R=DEC #i nclude P16F877.INC ;*********************************** Errorlevel -302,-305 __CONFIG _DEBUG_OFF&_CP_ALL&_CPD_ON&_LVP_OFF&_BODEN_OFF&_PWRTE_ON&_WDT_OFF&_HS_OSC; ;***********************************寄存器定義 CBLOCK 0x20 JP YP L1 L2 TA:2 COUNT1 COUNT2 W_STACK ST_STACK ENDC ;************************************ ORG 0X0000 nop ;放置一條MCD所必須的空指令 GOTO MAIN ;主程序 ORG 0x0004 BTFSC PIR1,TMR1IF ;中斷子程序 GOTO T1 ;轉T1處理 RETFIE ORG 0x0010 ;************************************ MAIN CLRWDT ;喂狗 BCF STATUS,RP0 CLRF INTCON ;清除其他中斷標志位 CLRF PORTC CLRF PIR1 ;清除TMR1中斷標志位 BSF STATUS,RP0 BSF PIE1,0 ;使能TMR1中斷 MOVLW B'10111111' ;除RC6口輸出外,其他口都設為輸入 MOVWF TRISC BCF STATUS,RP0 MOVLW 0xC0 ;開啟中斷總允許位GIE跟PEIE MOVWF INTCON REPLAY CLRF COUNT1 ;從頭開始查表(亦即從頭開始唱歌) SING CLRF TMR1L CLRF TMR1H ;清零TMR1定器 MOVF COUNT1,0 CALL TABLE MOVWF COUNT2 ;暫存查表結果于COUNT2中 BCF STATUS,Z SUBLW 0x00 ;判斷是否查表到最后一個數值 BTFSC STATUS,Z GOTO REPLAY ;是,說明音樂播放完成,重頭開始播放 MOVF COUNT2,0 ANDLW 0x0F ;去掉高4位只保留低4位 MOVWF JP ;保存到JP中 SWAPF COUNT2,0 ;高低半字節交換 ANDLW 0x0F ;去掉高4位只保留低4位 MOVWF YP ;保存到YP中,這樣查表的結果的被分成高低半字節兩部分分別存放在YP跟JP中 DECF YP,1 MOVF YP,0 CALL TABLE_YP MOVWF TMR1H ;作為TMR1初值的高8位 MOVWF TA ;暫存TA中 INCF YP,0 CALL TABLE_YP MOVWF TMR1L ;作為TMR1初值的低8位 MOVWF TA+1 ;暫存TA+1中 BSF T1CON,TMR1ON ;開啟TMR1定時器 CALL DELAY ;延時一段時間 INCF COUNT1 ;COUNT1加1,以便查表得到下一個播放的音調 GOTO SING ;返回播放下一個音調 ;**************************延時程序 DELAY MOVLW 200 MOVWF L1 DELAY_1 MOVLW 225 MOVWF L2 DELAY_2 DECFSZ L2,1 GOTO DELAY_2 DECFSZ L1,1 GOTO DELAY_1 DECFSZ JP,1 GOTO DELAY CLRWDT RETURN ;*************************中斷現場保護 PUSH MOVWF W_STACK ;保存W的值 MOVF STATUS,0 MOVWF ST_STACK ;保存STATUS的值 RETURN ;************************中斷現場恢復 POP MOVF ST_STACK,0 MOVWF STATUS ;恢復STATUS的值 MOVF W_STACK,0 ;恢復W的值 RETURN ;************************中斷處理子程序 T1 CALL PUSH ;調用現場保護程序 MOVLW 0x40 ;RC6口輸出取反 XORWF PORTC,1 MOVF TA,0 MOVWF TMR1H MOVF TA+1,0 MOVWF TMR1L ;給TMR1賦初值 BSF T1CON,TMR1ON ;開啟定時器 BCF PIR1,TMR1IF ;清除標志位 CALL POP ;調用現場恢復程序 RETFIE TABLE_YP ADDWF PCL,1 RETLW 0xFC ;1 RETLW 0x44 RETLW 0xFC ;2 RETLW 0xAC RETLW 0xFD ;3 RETLW 0x09 RETLW 0xFD ;4 RETLW 0x34 RETLW 0xFD ;5 RETLW 0x82 RETLW 0xFD ;6 RETLW 0xC8 RETLW 0xFE ;7 RETLW 0x06 TABLE ADDWF PCL,1 RETLW 0x14 RETLW 0x34 RETLW 0x54 RETLW 0x14 RETLW 0x14 RETLW 0x34 RETLW 0x54 RETLW 0x14 RETLW 0x54 RETLW 0x74 RETLW 0x98 RETLW 0x54 RETLW 0x74 RETLW 0x98 RETLW 0x93 RETLW 0xB1 RETLW 0x93 RETLW 0x71 RETLW 0x54 RETLW 0x14 RETLW 0x93 RETLW 0xB1 RETLW 0x93 RETLW 0x71 RETLW 0x54 RETLW 0x14 RETLW 0x14 RETLW 0x94 RETLW 0x18 RETLW 0x14 RETLW 0x94 RETLW 0x18 RETLW 0x00 ;******************************************** end ;源程序結束 ;******************************************** ; 進入該實戰演練的工序流程如下: ; 1.創建源文件和編輯源文件;在此介紹一種不同于前面講的創建源文件的方法,用Windows附件中的”記事本” ; 這個為大家所熟知和好用的文件編輯器,并且可以方便的加入中文注釋.不過有兩點需要注意,一是注釋前面的 ; 分號”;”必須用西文半角輸入;二是必須用”.asm”擴展名存儲到事先建立的一個專用子目錄下. ; 2.打開MPLAB集成開發環境:首先在WINDOWS環境下,選用開始>程序>Microchip MPLAB>MPLAB命令,啟動MPLAB ; 并進入MPLAB的桌面. ; 3.創建項目:選用菜單File>New或Project>New Project,在事先建立的一個專用子目錄下創建一個新項目,將 ; 用記事本創建的源文件加入到該項目中. ; 4.建立項目中的目標文件:選擇菜單Project >Build All(項目>建立所有文件),MPLAB將自動調用MPASM將項目 ; 文件管理下的源文件(.asm)匯編成十六進制的目標文件(.hex).
MOVFW CSR0A ;將臨時寄存器中的數存回相應寄存器 MOVWF CSR0 MOVFW CSR1A MOVWF CSR1 MOVFW CSR2A MOVWF CSR2 MOVFW CSR3A MOVWF CSR3 COMF CSR0,0 ;比較鍵碼的反碼取反后是否等于鍵碼 XORWF CSR1,0 BNZ LOOP ;不等于則接收到的是錯誤的信息 ;將鍵碼送顯示 SWAPF CSR1,W ;顯示值高低位交換,先處理高位 ANDLW 0FH ;屏蔽掉高位 MOVWF DISPBUF_H ;存入寄存器 MOVFW CSR1 ;顯示值低位處理 ANDLW 0FH ;屏蔽掉高位 MOVWF DISPBUF_L ;存入寄存器 GOTO LOOP ;------------------------------------------------------ END ;*********************************************************** ; 進入該實戰演練的工序流程如下: ; 1.創建源文件和編輯源文件;在此介紹一種不同于前面講的創建源文件的方法,用Windows附件中的”記事本” ; 這個為大家所熟知和好用的文件編輯器,并且可以方便的加入中文注釋.不過有兩點需要注意,一是注釋前面的 ; 分號”;”必須用西文半角輸入;二是必須用”.asm”擴展名存儲到事先建立的一個專用子目錄下. ; 2.打開MPLAB集成開發環境:首先在WINDOWS環境下,選用開始>程序>Microchip MPLAB>MPLAB命令,啟動MPLAB ; 并進入MPLAB的桌面. ; 3.創建項目:選用菜單File>New或Project>New Project,在事先建立的一個專用子目錄下創建一個新項目,將 ; 用記事本創建的源文件加入到該項目中. ; 4.建立項目中的目標文件:選擇菜單Project >Build All(項目>建立所有文件),MPLAB將自動調用MPASM將項目 ; 文件管理下的源文件(.asm)匯編成十六進制的目標文件(.hex). ; 5.ICD參數設置:通過菜單命令Project>Edit Project或者Option>Development Mode,將開發模式設置為 ; ”MPLAB ICD Debugger”,點擊OK按鈕,打開ICD的工作窗口,在調試階段,可以按照說明書圖2-10設置各項,但需注意 ; OSCILLATOR應設置為XT方式,尤其需要說明的是,選中“Enable Debug Mode”(使能調試模式)選項,在向目 ; 標單片機燒寫機器碼程序時,會將調試臨控程序同時寫入單片機的指定程序存儲器區域,然后才允許用ICD方式調試。 ; 6.電路設置:將演示板的S1全部拔到OFF,S13的第3位拔到ON其它位OFF,S4全部拔到ON,S5的第5第6位拔到ON其它位OFF,LCD不要插在演示板上, ; 將用于選擇頻率的插針跳線插到”XT OSC”位置上,板上93CXX、24CXX應拿下。 ; 7.向目標單片機燒寫目標程序:用戶在點擊功能按鈕”Program”向目標單片機燒寫機器碼程序時,會等待一段時間, ; 并且在條狀的狀態信息欄中,出現提示信息。有一點需要引起注意,就是PIC16F87X單片機的FLASH程序存儲器的擦寫 ; 周期是有限的,大約為1000次,應盡量節省它的使用壽命。 ; 8.運行和調試用戶程序和用戶電路:在各項參數設置好后,將ICD的工作窗口最小化,利用前面講的”運行及調試”中介 ; 紹的幾種方法進行調試.當用自動單步方式調試時,建議臨時禁止廷時子程序發揮作用,具體的方法是,可在CALL DELAY指 ; 令前添加一個分號,并且重新匯編一次.為了學習目的,在調試過程中可以人為地加入一些軟件漏洞(BUG)或硬件故障,來模 ; 仿單片機端口引腳的片內或片外故障. ; 9.定型燒寫目標單片機;經過多次重復上述步驟的反復修改和調試,使得程序和電路在聯機狀態完全正常,這時可以進行 ; 定型燒寫,即將ICD窗口中的”Enable Debug Mode”(使能調試模式)選項消除,不再將調試臨控程序寫入單片機中. ; 10.獨立運行驗收:上一步中的燒寫過程完成后,即可將ICD模塊和ICD仿真頭(或演示板)之間的6芯電纜斷開,讓單片機在 ; 演示板獨立運行,觀察實際效果.
|