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