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