目次8章.機能が豊富なPICを使う(PIC12F683)PWM機能を使ってスピーカを鳴らす(ドレミ〜を演奏)>ソース

PWM機能を使ってスピーカを鳴らす(ソース)

(ドレミ〜を演奏)
更新日2006.4.5

以下のソースを取り込んで、アセンブル→PIC書き込み→実行して下さい。

; ========================== ここから ==============================
;
;	PIC12F683
;	clock:INTOSCIO 4MHz
;
;	PWMの動作確認(ドレミファソラシドを演奏)
;	デューティは固定で周期を変える
;
;	GP2(CCP1:PWM) : スピーカ
;	GP5      : LED(0.5秒間隔で点滅)
;
;	TMR0割込み
;	TMR0:0(フリーラン)
;	プリスケーラ:使用しない
;	割込み周期:(1S/4MHz)*4*256 = 256uS
;
;
	LIST	P=12f683
	#INCLUDE <p12f683.inc>

	__CONFIG _CP_OFF & _CPD_OFF & _WDT_OFF & _BOD_ON & _IESO_OFF& _PWRTE_ON & _INTOSCIO & _MCLRE_OFF


save_st	EQU	020h		; STATUSのセーブ領域
save_w	EQU	021h		; W-regのセーブ領域
CNT10mS	EQU	022h		; TMR0割り込み(256uS)を39回カウントするカウンタ=9.984mS
CNT01S	EQU	023h		; 9.984mSを10回カウントするカウンタ=99.84mS
CNT05S	EQU	024h		; 99.84mSを5回カウントするカウンタ=499.2mS
mus	EQU	025h		; 音階コード(0:ド,1:レ,2:ミ......)
timer	EQU	026h		; タイマフラグ(0:256uS,1:10mS,2:100mS,3:500mS)
T256uS	EQU	00h			; TMR0割込み
T10mS	EQU	01h			; 10mS
T100mS	EQU	02h			; 100mS
T500mS	EQU	03h			; 500mS


	ORG	0
	GOTO	INIT

; ==============================================================
	ORG	4
;	TMR0割込み
INTR
	BCF	INTCON,T0IF	;割込みフラグクリア
	MOVWF	save_w		;W-regセーブ
	SWAPF	STATUS,W
	MOVWF	save_st		;STATUSレジスタセーブ

	BSF	timer,T256uS	;256uSフラグセット

	DECFSZ	CNT10mS,F
	GOTO	INTR90
	MOVLW	d'39'
	MOVWF	CNT10mS		;10mSカウンタ初期化
	BSF	timer,T10mS	;10mSフラグセット

	DECFSZ	CNT01S,F
	GOTO	INTR90
	BSF	timer,T100mS	;100mSフラグセット
	MOVLW	d'10'
	MOVWF	CNT01S		;100mSカウンタ初期化

	DECFSZ	CNT05S,F
	GOTO	INTR90
	BSF	timer,T500mS	;500mSフラグセット
	MOVLW	d'5'
	MOVWF	CNT05S		;500mSカウンタ初期化

INTR90
	SWAPF	save_st,W
	MOVWF	STATUS		;STATUSレジスタロード
	SWAPF	save_w,F
	SWAPF	save_w,W	;W-regロード
	RETFIE			;割込み許可リターン

; ==============================================================
;	PICの初期化
INIT
    ; GPIOをデジタルI/Oに設定
	MOVLW	07h  
	MOVWF	CMCON0		;GP2-0はデジタルIO  
	BSF	STATUS,RP0	;■バンク1に切替え
	CLRF	ANSEL		;デジタルIO(AN機能を使用しない)

    ; 内部クロックを4MHzに設定
	MOVLW	060h
	MOVWF	OSCCON		; CLOCK=4MHz

    ; PWMの設定
	CLRF	TRISIO		; GP0-5は出力
	MOVLW	D'239'
	MOVWF	PR2		;PWM周期
	BCF	STATUS,RP0	;■バンク0に切替え
	MOVLW	D'119'
	MOVWF	CCPR1L		;PWMデューティーサイクル
	MOVLW	0Ch
	MOVWF	CCP1CON		;PWMモード
	MOVLW	07h
	MOVWF	T2CON		;Timer2 ON ,プリスケーラ:16
	CLRF	TMR2

    ; タイマ用カウンタの設定
	MOVLW	d'39'
	MOVWF	CNT10mS		; TMR0割り込み(256uS)を39回カウントするカウンタ=9.984mS
	MOVLW	d'10'
	MOVWF	CNT01S		; 9.984mSを10回カウントするカウンタ=99.84mS
	MOVLW	d'5'
	MOVWF	CNT05S		; 99.84mSを5回カウントするカウンタ=499.2mS
	CLRF	timer


    ; TMR0割込みの設定
	BSF	STATUS,RP0	;■バンク1に切替え
	MOVLW	08h		;プリスケーラ:使用しない(WDTに割り当て)
	MOVWF	OPTION_REG
	BCF	STATUS,RP0	;■バンク0に切替え
	CLRF	TMR0		;TMR0セット
	MOVLW	0A0h		;TMR0割り込みを使用する
	MOVWF	INTCON


    ; 音階の初期設定
	CLRF	mus


; ==============================================================
;    メイン処理
MAIN
	BTFSC	timer,T500mS	;500mSフラグセット?
	CALL	S500mS

	GOTO	MAIN


;  ===== 500mS経過処理 =====
S500mS
	BCF	timer,T500mS	;500mSフラグクリア

;  音階設定
	INCF	mus,F		;音階カウントアップ
	BTFSC	mus,3		;1オクターブ終了?
	CLRF	mus		; Yes
	MOVF	mus,W
	CALL	doremi
	BSF	STATUS,RP0	;■バンク1に切替え
	MOVWF	PR2		;PWM周期
	BCF	STATUS,C
	RRF	PR2,W		;周期を1/2にする
	BCF	STATUS,RP0	;■バンク0に切替え
	MOVWF	CCPR1L		;1/2にした周期をデューティにセット
	CLRF	TMR2


;  LED点滅(0.5秒毎)
	MOVLW	020h		;GP5を
	XORWF	GPIO,F		;前回ONならOFFに、OFFならONに

	RETURN


;  ===== ドレミファソラシド =====
doremi
	ADDWF	PCL,f

	RETLW	d'239'	;ド
	RETLW	d'213'	;レ
	RETLW	d'190'	;ミ
	RETLW	d'179'	;ファ
	RETLW	d'159'	;ソ
	RETLW	d'142'	;ラ
	RETLW	d'126'	;シ
	RETLW	d'119'	;ド

        END
; =========================== ここまで ===============================