; list p=PIC12F675 ; ; Copyright 2004 Sugihara Toshio. ; All rights reserved. ; MT02 version. #include ; PIC12F675 ; Clock=4.00MHz 1.00M orders / s ; WDT=off, PowerUpTimer=on ; Protect=off, Oscllator=XT ; GP3=Digital IO, BrownOutDetect=off ; Timer Value tm1 equ H'20' tm2 equ H'21' tm3 equ H'22' tm4 equ H'23' tmc equ H'24' ; コンデンサ充電用タイマ loopa equ H'25' ;2ターン鳴らすための繰り返し用 ;Status Value 0=ON 1=OFF bakpos equ H'30' ;Saved Value curpos equ H'31' ;Current Value hazime equ H'32' ;Not 0 if just after boot ;Boot from here Boot org H'00' goto Start ;Interrupt comes here Warikomi org H'04' clrf STATUS ;Select Bank 0 movf GPIO, W ;Read GPIO to stop warikomi status clrf INTCON ;Clear GPIF retfie Start ;Stop interrupt clrf STATUS clrf INTCON ;Set Initial Value movlw H'01' movwf hazime INITIO ;I/O setup clrf STATUS clrf INTCON movlw B'00000001' movwf GPIO movlw H'07' ;Set GP2,GP1,GP0 to movwf CMCON ;Digital I/O bsf STATUS,RP0 ;Select Bank 1 clrf ANSEL ;Select GP3-0 to Digital I/O movlw H'08' ;Set GP0-GP2 into outputs movwf TRISIO ;GP3 is only input movlw B'11010110' ;prescaler is for TMR0 and 128:1 movwf OPTION_REG ;Pull up is globally off clrf WPU ;Pull up is off by every pin clrf IOC ; 割り込みピンの設定を消しておく bcf STATUS,RP0 ;Select Bank 0 movlw B'00000001' movwf GPIO ;Set I/O stop mode ;Read current Status call ReadButton btfsc hazime,0 ; 起動直後? goto Afterring ; はい。鳴らした後の場所へ行く ; いいえ。 movf curpos,W subwf bakpos,W ; W := bakpos - curpos btfsc STATUS,Z ; bakpos==curpos ? goto Afterring ; はい。鳴らした後の場所へ行く ; いいえ。鳴らします Ring movlw D'2' movwf loopa ; 2ターン鳴らす RingRepeat ;Dを鳴らす movlw D'207' ; 207周期鳴らす movwf tm3 movlw D'3' movwf tmc ; 充電はおよそ3周期 bcf GPIO, 0 ; Cに充電開始 RingE1 ; ここから851命令サイクルで半波長 bcf GPIO, 2 ; Bを下げる bsf GPIO, 1 ; Aを上げる movlw D'212' movwf tm1 ; 待ちの量を指定 RingE2 nop decfsz tm1,f goto RingE2 ; ここから852命令サイクルで半波長 bcf GPIO, 1 ; Aを下げる bsf GPIO, 2 ; Bを上げる movlw D'210' ; 待ちの量を指定 movwf tm1 RingE3 nop decfsz tm1,f goto RingE3 ; 843サイクル ; 必要に応じてCの充電を終わる decf tmc,f btfsc STATUS,Z ; 充電終了? bsf GPIO, 0 ; はい。止めます。 ; いいえ。 nop nop nop ; 849サイクル decfsz tm3,f goto RingE1 ; 852サイクル ; Aを鳴らす RingC movlw D'2' ; (この値 - 1)*256周期を追加 movwf tm4 movlw D'54' ; 256 + 54 = 310周期鳴らす movwf tm3 movlw D'2' movwf tmc bcf GPIO, 0 ; Cに充電開始 RingC1 ; ここから1136命令サイクルで半波長 bcf GPIO, 2 ;Bを下げる bsf GPIO, 1 ;Aを上げる movlw D'226' movwf tm1 ; 待ちの量を指定 RingC2 nop nop decfsz tm1,f goto RingC2 nop nop nop ; ここから1137命令サイクルで半波長 bcf GPIO, 1 ; Aを下げる bsf GPIO, 2 ; Bを上げる movlw D'224' ; 待ちの量を指定 movwf tm1 RingC3 nop nop decfsz tm1,f goto RingC3 ; 1123サイクル ; 必要に応じてCの充電を終わる decf tmc,f btfsc STATUS,Z ; 充電終了? bsf GPIO, 0 ; はい。止めます。 ; いいえ。 ; 1126 ; 鳴るのは終わり? decfsz tm3,f goto RingCX1 decfsz tm4,f goto RingCX2 goto RingG RingCX1 ; 1129 goto RingCX2 RingCX2 ; 1131 nop nop nop nop goto RingC1 ;1137 RingG decfsz loopa,f ; 指定の回数鳴らした? goto RingRepeat ; いいえ。鳴らすターンを繰り返す ; はい。 ; 鳴らした後はI/Oを確実に停止状態にする RingStop movlw B'00000001'; I/Oピンを停止状態に設定する movwf GPIO bsf STATUS,RP0 ;Select Bank 1 movlw H'08' ;Set GP0-GP2 as outputs movwf TRISIO ;GP3 is only input clrf STATUS ;Select Bank 0 movlw B'00000001'; I/Oピンを停止状態に設定する movwf GPIO ; 現在の状態をここで再び取得 call ReadButton ;鳴った後・鳴らなかった場合の動作 Afterring ; 変数の更新 clrf hazime ; もう初めてじゃない movf curpos,W ; bakpos = curpos movwf bakpos ; ; 状態固定用にGPIOを読む movf GPIO,W ;この読み込みを固定用とする movwf tm1 bcf tm1,0 btfsc tm1,3 bsf tm1,0 ;tm1::bit0 はスイッチの状態と同じ movf curpos,W ; スイッチとcurposは xorwf tm1,F ; tm1::bit0 = 一致で0 不一致で1 btfsc tm1,0 ; 不一致してる? goto AfterSleep ; はい。スリープの後の状態へ ; いいえ。 ; 割り込みの設定 bsf STATUS,RP0 ;Select Bank 1 movlw B'00001000';Set GP3 as movwf IOC ;interruptable bit clrf STATUS ;Select bank 0 clrf INTCON ;Clear INTCON bsf INTCON, 3 ;Set Port change enable bit bsf INTCON, 7 ;Set Global Interrupt Enable bit ; Sleep する sleep nop ; 割り込みする前にこれが実行されると思う nop ; 割り込みのあとはここから実行される AfterSleep ;起きた後。割り込みを禁止してI/O初期化からはじめる clrf INTCON nop nop goto INITIO ; スイッチの状態をcurposに入れて返す。 ; ON=0 OFF=1 ; 最短で1.5ms。最大で3.5msくらいで判断できる。 ReadButton ; 変数の初期化 clrf curpos ; 初期状態はオン扱い clrf tm1 ; オンの回数 clrf tm2 ; オフの回数 ReadButtonNext ; 6cycles / loop btfss GPIO,3 ; 押されてる? goto ReadButtonOn ; はい。オン。 ; いいえ。オフ。 ReadButtonOff nop incfsz tm2,F ; 256回め? goto ReadButtonNext ; いいえ。もう一度 ; はい。オフに決定 incf curpos,F ; curposをH'01'にする return ReadButtonOn incfsz tm1,F ; 256回め? goto ReadButtonNext ; いいえ。もう一度 ; はい。オンに決定 return ; curposは0のままで返す end