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