目次>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
; =========================== ここまで ===============================