目次>5章 第2ステップ(色々な実験)>スピーカを使って音を出す(追加実験)>ソース
スピーカを使って音を出す(ドレミ)
更新日2006.2.28
以下のソースを取り込んで、アセンブル→PIC書き込み→実行して下さい。
; ========================== ここから ==============================
; スピーカを鳴らす(ドレミファソラシドを演奏)
;
; PIC16F84A
; CLOCK : 20MHz
; PORTA 0 : OUT スピーカ(LM386で増幅)
; PORTA 2 : OUT LED(0.5秒間隔で点滅)
;
; プリスケーラ : なし
; TMR0初期値 : 128(設定値は138)
; TMR0割込み周期 : 25.6uS
;
LIST P=PIC16F84A
INCLUDE P16F84A.INC
__CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF
timer EQU 011h
save_st EQU 012h ;STATUSのセーブ
save_w EQU 013h ;W-regのセーブ
cnt5m EQU 014h ;5mSカウンタ(195) 0.0256mS*195=4.992mS
cnt500m EQU 015h ;500mSカウンタ(100)
cnt1Hz EQU 016h ;周波数(波長)値(tmr0割込み回数)
cnt1Hzi EQU 017h ;周波数(波長)値(tmr0割込み回数)の初期値
cnt1mus EQU 018h ;音階(ドレミファソラシド)の指定
; timer のビット位置
T25uS EQU 0 ;0.0256mSフラグ
T500mS EQU 3 ;500mSフラグ
counti EQU d'75' ;周波数カウントの初期値
ORG 0
GOTO init
; ●===== 割り込み処理 (タイマ)=====
ORG 4 ;割込みの入口
intr
BCF INTCON,T0IF ;割込みフラグクリア
MOVWF save_w ;W-regセーブ
SWAPF STATUS,W
MOVWF save_st ;STATUSレジスタセーブ
MOVLW d'138'
MOVWF TMR0
BSF timer,T25uS ;0.0256mSフラグセット
DECFSZ cnt5m,F
GOTO intr90
MOVLW d'195'
MOVWF cnt5m ;5mSカウンタ初期化
DECFSZ cnt500m,F
GOTO intr90
BSF timer,T500mS ;500mSフラグセット
MOVLW d'100'
MOVWF cnt500m ;500mSカウンタ初期化
intr90
SWAPF save_st,W
MOVWF STATUS ;STATUSレジスタロード
SWAPF save_w,F
SWAPF save_w,W ;W-regロード
RETFIE ;割込み許可リターン
; ●===== 初期処理 =====
init
CLRF timer ;タイマフラグクリア
CLRF cnt1mus ;音階クリア
MOVLW d'195'
MOVWF cnt5m ;5mSカウンタ初期化
MOVLW d'100'
MOVWF cnt500m ;500mSカウンタ初期化
MOVLW counti
MOVWF cnt1Hz
MOVWF cnt1Hzi
BSF STATUS,RP0 ;■バンク1に切替え
MOVLW 0FAh
MOVWF TRISA ;RA0,2は出力
MOVLW 08h ;プリスケーラ:使用しない(WDTに割り当て)
MOVWF OPTION_REG
BCF STATUS,RP0 ;■バンク0に切替え
CLRF PORTA ;PORTAをクリア
MOVLW d'138'
MOVWF TMR0 ;TMR0セット
MOVLW 0A0h ;TMR0割り込みを使用する
MOVWF INTCON
; ===== メイン処理 =====
BSF PORTA,2
main
BTFSC timer,T25uS ;0.0256mSフラグON?
CALL s25u ;YES
BTFSC timer,T500mS ;500mSフラグON?
CALL s500m ;YES
GOTO main
; ===== 0.0256mSサブルーチン
; 一定周期のパルスを発生させる。
; ・周期は"cnt1Hzi"で指定する
; ・パルスの出力はRA0
s25u
BCF timer,T25uS ;0.0256mSフラグをクリア
DECFSZ cnt1Hz,F ;1/2サイクル経過?
GOTO s25u90 ; NO
MOVF cnt1Hzi,W
MOVWF cnt1Hz
MOVLW 01h
XORWF PORTA,F ;RA0を反転させる
s25u90
RETURN
; ===== 500mSサブルーチン
; 音階設定 と
; RA2のLEDを0.5秒毎にON/OFFさせる(タイマ動作の確認用)
s500m
BCF timer,T500mS ;500mSフラグをクリア
; 音階設定
INCF cnt1mus,F ;音階カウントアップ
BTFSC cnt1mus,3 ;1オクターブ終了?
CLRF cnt1mus ; Yes
MOVF cnt1mus,W
CALL doremi
MOVWF cnt1Hzi
; パイロットランプ(RA2)点滅
MOVLW 04h
XORWF PORTA,F ;RA2を反転させる
s500m90
RETURN
; ===== ドレミファソラシド =====
doremi
ADDWF PCL,f
RETLW d'75' ;ド
RETLW d'67' ;レ
RETLW d'59' ;ミ
RETLW d'56' ;ファ
RETLW d'50' ;ソ
RETLW d'44' ;ラ
RETLW d'40' ;シ
RETLW d'37' ;ド
END
; =========================== ここまで ===============================