目次>6章 第3ステップ(実用品)>(3)拍手スイッチ>拍手スイッチ ソフトウェア編>ソース
拍手スイッチ ソフトウェア編(PIC12F683)(ソース)
更新日2006.9.20
以下のソースを取り込んで、アセンブル→PIC書き込み→実行して下さい。
; ========================== ここから ==============================
;
; PIC12F683
; clock:INTOSCIO 1MHz
;
; 拍手スイッチ
; GP3 : 拍手信号(ピン変化割り込み)
; GP0-2 : LED(ピン変化割込み回数を2進数で表示)
;
; GP3の入力とGP0-2出力の関係
;
; GP3
; "1","."は1文字約100mS 拍手の音 GP0-2
; 1.1.1...1...1... パパパンパンパン GP0 ON
; 1.1...1.1.1.1... パパン パパパパン GP1 ON
; 1.1...1.1.1.1.1... パパン パパパパパン GP2 ON
;
;
; TMR0割込み
; TMR0:0(フリーラン)
; プリスケーラ:使用しない
; 割込み周期:(1S/1MHz)*4*256 = 1024uS(マイクロ秒)
;
;
; 変更履歴
; 2006.09.10 GP0の拍手パターンを変更
; 2006.09.20 SLEEPにする直前で割込みが発生すると割り込み禁止から
; 抜けなくなるバグ修正
; (ピン変化割込みルーチンで、状態が3なら何もしない)
;
;
LIST P=12f683
#INCLUDE <p12f683.inc>
__CONFIG _CP_OFF & _CPD_OFF & _WDT_OFF & _BOD_OFF & _IESO_OFF& _PWRTE_ON & _INTOSCIO & _MCLRE_OFF
save_st EQU 020h ; STATUSのセーブ領域
save_w EQU 021h ; W-regのセーブ領域
iocflag EQU 022h ; 割り込みフラグ
CNT10mS EQU 023h ; TMR0割り込み(1024uS)を10回カウントするカウンタ=10.24mS
timer EQU 024h ; タイマフラグ(0:256uS,1:1mS,2:10mS)
T1mS EQU 01h ; 1mS (1.024mS)
T10mS EQU 02h ; 10mS(10.24mS)
TM10mS EQU 025h ; 10mS単位の時間
STATE EQU 026h ; 状態
; 1 : ピン変化割り込み発生で90mS割り込み禁止
; 2 : ピン変化割り込みを認識し、次のピン変化割り込みを待つ
; 3 : 600mS以上ピン変化割り込みが無くSLEEPになる前の50mS間(ピン変化割り込み禁止)
WORK1 EQU 027h
rhythm EQU 028h ; リズム(拍手の間隔の組み合わせ)
ORG 0
GOTO INIT
; ==============================================================
ORG 4
; 割込み処理(ピン変化割り込み&TMR0割り込み)
MOVWF save_w ;W-regセーブ
SWAPF STATUS,W
MOVWF save_st ;STATUSレジスタセーブ
BTFSC INTCON,GPIF ;ピン変化割込み?
GOTO INTR_CHG ; Yes
BTFSC INTCON,T0IF ;TMR0割込み?
GOTO INTR_T0 ; Yes
GOTO INTR_EXIT
; ■TMR0割り込み
INTR_T0
BCF INTCON,T0IF ;TMR0割込みフラグクリア
BSF timer,T1mS ;1mSフラグセット
DECFSZ CNT10mS,F
GOTO INTR_EXIT
BSF timer,T10mS ;10mSフラグセット
MOVLW d'10'
MOVWF CNT10mS ;10mSカウンタ初期化
INCF TM10mS,F ;10mS単位の時間カウントアップ
; ■ピン変化割り込み
INTR_CHG
BCF INTCON,GPIF ;ピン変化割込みフラグクリア
BTFSS GPIO,3 ;0→1の変化のみ拾う
GOTO INTR_EXIT
BTFSC STATE,3 ;STATE=3?
GOTO INTR_EXIT ;Yes
BSF iocflag,0 ;ピン変化割り込みフラグON
BSF STATUS,RP0 ;■バンク1に切替え
CLRF IOC ;ピン変化割り込み中断
BCF STATUS,RP0 ;■バンク0に切替え
GOTO INTR_EXIT
INTR_EXIT
SWAPF save_st,W
MOVWF STATUS ;STATUSレジスタロード
SWAPF save_w,F
SWAPF save_w,W ;W-regロード
RETFIE ;割込み許可リターン
; ==============================================================
; PICの初期化
INIT
; GPIOをデジタルI/Oに設定
CLRF GPIO
MOVLW 07h
MOVWF CMCON0 ;GP2-0はデジタルIO
BSF STATUS,RP0 ;■バンク1に切替え
CLRF ANSEL ;デジタルIO(AN機能を使用しない)
MOVLW 028h ;GP0-2,4:output GP3,5:input (DEBUG)
; MOVLW 038h ;GP0-2:output GP3-5:input
MOVWF TRISIO
; 内部クロックを1MHzに設定
MOVLW 040h
MOVWF OSCCON ; CLOCK=1MHz
; ピン変化割り込み設定,TMR0割り込み許可
MOVLW 08h
MOVWF IOC ; GP3:ピン変化割り込み有効
BCF STATUS,RP0 ;■バンク0に切替え
MOVLW 0A8h ; GIE,T0IE,GPIE on
MOVWF INTCON
; TMR0割込みの設定
BSF STATUS,RP0 ;■バンク1に切替え
MOVLW 08h ;プリスケーラ:使用しない(WDTに割り当て)
MOVWF OPTION_REG
BCF STATUS,RP0 ;■バンク0に切替え
CLRF TMR0 ;TMR0クリア
CLRF STATE ;状態
CLRF iocflag ;ピン変化割り込みフラグ
CLRF rhythm ;リズム(拍手の間隔の組み合わせ)
MOVLW d'10'
MOVWF CNT10mS ;10mSカウンタ初期化
; ==============================================================
; メイン処理
MAIN
BTFSC timer,T10mS ;10mS経過?
CALL p10mS ; Yes
BTFSC iocflag,0 ;ピン変化割り込み発生?
CALL pin_chg ; Yes
GOTO MAIN ; No
; ==============================================================
; 10mS経過処理
p10mS
BCF timer,T10mS ;10mS割り込みフラグクリア
BTFSC STATE,1 ;STATE=1?
GOTO p10_1 ;Yes
;No
BTFSC STATE,2 ;STATE=2?
GOTO p10_2 ;Yes
;No
BTFSC STATE,3 ;STATE=3?
GOTO p10_3 ;Yes
GOTO p10_exit ;No
p10_1
call stat1
GOTO p10_exit
p10_2
call stat2
GOTO p10_exit
p10_3
call stat3
GOTO p10_exit
p10_exit
RETURN
; ==============================================================
; 状態(STATE)=1の処理
stat1
MOVLW d'9' ;
SUBWF TM10mS,W ;TM10mS=9?(ピン変化割り込みから90mS経過?)
BTFSC STATUS,Z ;
GOTO stat1_1 ;Yes
GOTO stat1_exit ;No
stat1_1
; 状態(STATE)が1で90mS経過
BCF GPIO,4 ;DEBUG ピン変化割り込み毎にLEDを点滅
CALL tm_clr ;タイマ用カウンタ等初期化処理
MOVLW 04h
MOVWF STATE ;状態(STATE)を2に
MOVF GPIO,W ;割り込み許可する前にダミーREAD
BSF STATUS,RP0 ;■バンク1に切替え
MOVLW 08h
MOVWF IOC ; GP3:ピン変化割り込み有効
BCF STATUS,RP0 ;■バンク0に切替え
stat1_exit
RETURN
; ==============================================================
; 状態(STATE)=2(ピン変化割り込み待ち)の処理
stat2
MOVLW d'60' ;
SUBWF TM10mS,W ;TM10mS >= 60?(ピン変化割り込みなしで600mS経過?)
BTFSS STATUS,C ;
GOTO stat2_exit ;No
; 状態(STATE)が2で600mS経過
BSF STATUS,RP0 ;■バンク1に切替え
CLRF IOC ;ピン変化割り込み中断
BCF STATUS,RP0 ;■バンク0に切替え
; rhythm(リズム)の判定
MOVLW b'00000101' ;パパンパパン
SUBWF rhythm,W
BTFSC STATUS,Z
GOTO stat2_1
MOVLW b'0001100' ;パパパンパンパン
SUBWF rhythm,W
BTFSC STATUS,Z
GOTO stat2_2
MOVLW b'00010111' ;パパンパパパパン
SUBWF rhythm,W
BTFSC STATUS,Z
GOTO stat2_3
MOVLW b'00101111' ;パパンパパパパパン
SUBWF rhythm,W
BTFSC STATUS,Z
GOTO stat2_4
CALL tm_clr ;タイマ用カウンタ等初期化処理
GOTO stat2_exit0
stat2_1
CLRW
CALL cnt_disp ;GPIO(2−0)全てOFF
GOTO stat2_exit0
stat2_2
MOVLW 01h
CALL cnt_disp ;GP0のみON
GOTO stat2_exit0
stat2_3
MOVLW 02h
CALL cnt_disp ;GP1のみON
GOTO stat2_exit0
stat2_4
MOVLW 04h
CALL cnt_disp ;GP2のみON
GOTO stat2_exit0
stat2_exit0
CLRF rhythm
MOVLW 08h
MOVWF STATE ;状態(STATE)を3に
stat2_exit
RETURN
; ==============================================================
; 状態(STATE)=3の処理
stat3
MOVLW d'5' ;
SUBWF TM10mS,W ;TM10mS >= 5?(50mS STATE=3維持?)
BTFSS STATUS,C ;
GOTO stat3_exit ;No
BCF GPIO,4 ;DEBUG ピン変化割り込み毎にLEDを点滅
MOVF GPIO,W ;割り込み許可する前にダミーREAD
BSF STATUS,RP0 ;■バンク1に切替え
MOVLW 08h
MOVWF IOC ; GP3:ピン変化割り込み有効
BCF STATUS,RP0 ;■バンク0に切替え
SLEEP ;ピン変化割り込みで抜ける
MOVLW 02h
MOVWF STATE ;状態(STATE)を1に
BSF STATUS,RP0 ;■バンク1に切替え
CLRF IOC ;ピン変化割り込み中断
BCF STATUS,RP0 ;■バンク0に切替え
CLRF rhythm ;リズム(拍手の間隔の組み合わせ)
CALL pin_chg
stat3_exit
RETURN
; ==============================================================
; ピン変化割り込み処理
pin_chg
BCF iocflag,0 ;ピン変化割り込みフラグクリア
BSF GPIO,4 ;DEBUG ピン変化割り込み毎にLEDを点滅
BTFSC STATE,2 ;状態 = 2?
CALL width_chk ;Yes (拍手の間隔チェック)
CALL tm_clr ;タイマ用カウンタ等初期化処理
BTFSC STATE,3 ;状態 = 3?
GOTO pin_chg9 ;Yes
MOVLW 02h
MOVWF STATE ;状態 '1'
pin_chg9
RETURN
; ==============================================================
; 拍手の間隔(リズム)チェック
; STATE=2でピン変化割り込み発生時
width_chk
MOVLW d'3' ;
SUBWF TM10mS,W ;TM10mS < 3?(前回割り込みから20mS以下?(対象外))
BTFSS STATUS,C ;
GOTO width_non ;Yes
MOVLW d'51' ;
SUBWF TM10mS,W ;TM10mS >= 51?(前回割り込みから510mS以上?(対象外))
BTFSC STATUS,C ;
GOTO width_non ;Yes
MOVLW d'21' ;
SUBWF TM10mS,W ;TM10mS < 21?(前回割り込みから200mS以下?(短拍))
BTFSS STATUS,C ;
GOTO width_s ;Yes
MOVLW d'30' ;
SUBWF TM10mS,W ;TM10mS >= 30?(前回割り込みから300mS以上?(長拍))
BTFSC STATUS,C ;
GOTO width_l ;Yes
GOTO width_non ;No
width_s ; 短拍 rhythmの0ビット目に1を挿入
BCF STATUS,C
RLF rhythm,F
BSF rhythm,0
GOTO width_exit
width_l ; 長拍 rhythmの0ビット目に0を挿入
BCF STATUS,C
RLF rhythm,F
BCF rhythm,0
GOTO width_exit
width_non
CALL tm_clr
MOVLW 08h
MOVWF STATE ;状態 '3'
width_exit
RETURN
; ==============================================================
; WをGPIO(2−0)に出力
cnt_disp
MOVWF WORK1
MOVLW 07h
ANDWF WORK1,F ;パラメータWの下位3ビットを取り出す
MOVLW 038h
ANDWF GPIO,W ;GP5-3を取り出す
IORWF WORK1,W ;パラメータWの下位3ビットを
MOVWF GPIO ;GP2-0にセット(GP5-3は変えない)
RETURN
; ==============================================================
; タイマ用カウンタ等初期化処理
tm_clr
CLRF TM10mS ;10mS単位の時間
MOVLW d'10'
MOVWF CNT10mS ;10mSカウンタ初期化
RETURN
END
; =========================== ここまで ===============================