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