;*************************************************** ; ;      王蟲ボディ電飾プログラム ver 1.2 ; 00/06/11 Masashi Kawanishi ; PIC16F84:10MHz用(1cycle=0.4us) ; ; スロットル 0〜5% 青EL強弱繰り返し ; 6〜75% 青点灯 ; 76%〜95% スロットル開度に比例して ;                   青徐々に消灯、赤徐々に点灯 ; 96%〜 青消灯 赤点灯 ; ; はじめの1秒の間にSW押すとスロットル調整モード ; (1)ニュートラルでSW押す(2)ハイポイントでSW ; ; ピンアサイン ; RA0 -> 動作チェック用LED (1でOFF 0でON) ; RA2 -> Blue EL (0でOFF 1でON) ; RA3 -> Red LED (0でOFF 1でON) ; RB4 <- スロットル入力 (0でOFF 1でON) ; RB5 <- プッシュSW (1でOFF 0でON) ; ;****************************************************** LIST P=PIC16F84 INCLUDE "P16F84.INC" ;****************************** ;     変数レジスタ定義 ;****************************** NTPINT equ 0EH ;ニュートラルポイントレジスタ ; ニュートラルポイントのパルス幅は ; 2982 + 6*NTPINT steps (*0.4us) ; NTPINT = 128 のとき 1500us ; NTPINT 0〜256で 1192.8〜1807.2us HGPINT equ 0FH ;ハイポイントレジスタ ; ハイポイントのパルス幅は ; 4232 + 6*HGPINT steps (*0.4us) ; HGPINT = 128 のとき 2000us ; HGPINT 0〜256で 1692.8〜2307.2us BRCNT equ 10H ; 呼吸間隔用カウンタ LCNT equ 11H ; 強度変化用(light期間) DCNT equ 12H ; 強度変化用(dark期間) ; 本ver.では分解能17stepsで15段階 E_ADRS equ 13H E_DATA equ 14H CNTa equ 19H ; Time counter CNTb equ 1AH CNTc equ 1BH CNTd equ 1CH CNTe equ 1DH CNTf equ 1EH ; f は汎用 CNTg equ 1FH ; g も汎用 ; ************************************ ;          初期化 ; ************************************ ORG 0 MAIN0 bsf STATUS, RP0 movlw b'00000000' ;RA set : all output movwf TRISA movlw b'11111111' ;RB set : all input movwf TRISB bcf STATUS, RP0 movlw b'00000001' movwf PORTA ;LED, EL消灯 movlw 9CH ;呼吸間隔カウンタ movwf BRCNT ;+100カウントでオーバーフロー call EEPRD ; EEPROM より設定値読み出し ; ********************************** ;          セッティングモードか? ; ********************************** MOVLW 0C8H ;set 200 MOVWF CNTe MAIN05 CALL TIME5M ; 2+(12753+7)*200-1=2552001=ca.1sec btfss PORTB, 5 ; SWが押されていなかったら(RB4=1)、スキップ goto STNG ; 押されたらセッティングモードへ DECFSZ CNTe,F GOTO MAIN05 ; ********************************** ;          メインルーチン ; **********************************  MAIN1 btfss PORTB, 4 ;スロットルパルスがあったら次をスキップ goto MAIN1 nop nop btfss PORTB, 4 ;ノイズ対策 goto MAIN1 ;(6 : 2.4us) ; ニュートラルポイント+62step (24.8usec = 約5%スロットル) ; まで待つ ; ニュートラルポイントのパルス幅は ; 2982 + 6*NTPINT steps call TIME1M ; 6+2+2553 = 2561 movlw 68H ;あと421 movwf CNTf MAIN2 nop decfsz CNTf, F ;2+4*104-1=417 goto MAIN2 ;2561+417 = 2978 nop nop movf NTPINT, W movwf CNTf ;(2982) MAIN3 nop nop nop decfsz CNTf, F ;6*NTPINT-1 goto MAIN3 nop ;ここまででニュートラルパルス幅 movlw 14H ;あと62 movwf CNTf MAIN4 decfsz CNTf, F ;2+3*20-1=61 goto MAIN4 nop ;(62) ; *** 呼吸モードに入るか? *** ;  (A) btfss PORTB, 4 ;スロットルパルスなしで呼吸モードへ goto BREATH ;(2) movlw 9CH ;呼吸間隔カウンタリセット movwf BRCNT ; (4) ; *** 巡航パルス幅の間「待ち」 *** ; 巡航パルス幅は(A)以降 ; 870 + 6*HGPINT-6*NTPINT (step) ; = 6 * 145(91H) + 6*HGPINT-6*NTPINT (step) movlw 08FH movwf CNTf movf HGPINT, w addwf CNTf, f movf NTPINT, w subwf CNTf, f MAIN5 nop nop nop decfsz CNTf, F ;6*(パルス幅-2)-1 goto MAIN5 nop nop nop ;パルス幅待ち完了 ; *** 巡航か? *** btfss PORTB, 4 ;スロットルパルスなしで巡航モードへ goto CRUISE ;(2) ; *** 「怒りかけ」か? *** movlw 10H movwf DCNT ; DCNTを減算しながらスロットル開度を測る ; 1カウント= 17steps=6.8us 最大15カウント MAIN6 decfsz DCNT, f goto MAIN7 goto MAIN8 MAIN7 ; (3) movlw 03H movwf CNTf ; (5) MAIN75 decfsz CNTf, f goto MAIN75 ; 5 + 8 = 13 nop btfsc PORTB, 4 goto MAIN6 ; (17) goto GANGRY ; **** 怒り100% *** MAIN8 movlw b'00001001' movwf PORTA ;青OFF, 赤ON MAIN9 btfsc PORTB, 4 goto MAIN9 ; シグナルがなくなるのを待って goto MAIN1 ; はじめに戻る ; ******************************** ;        呼吸モード  ; ******************************** BREATH movlw b'00000101' movwf PORTA ;青ON, 赤OFF incfsz BRCNT, f ;呼吸カウンタがオーバーフローしたら青強度変化 goto MAIN1 ;しなかったらパルス待ちへ戻る movlw 9CH movwf BRCNT ; BRCNTリセット ;  *** 息継ぎ開始 *** movlw 0FFH movwf LCNT ;LCNT = 0FFH movlw 01H movwf DCNT ;DCNT = 01H BREATH0 bsf PORTA, 2 ;青点灯 movf LCNT, w movwf CNTf ;LCNTの値をワーキングカウンタにコピー(3) BREATH1 nop nop nop nop nop nop nop nop nop decfsz CNTf, f goto BREATH1 ;LCNTの回数ループ bcf PORTA, 2 ;青消灯 movf DCNT, w movwf CNTf ;DCNTの値をワーキングカウンタにコピー BREATH2 nop nop nop nop nop nop nop nop nop decfsz CNTf, f goto BREATH2 ;DCNTの回数ループ incf DCNT, f decfsz LCNT, f goto BREATH0 ;全ループ終了で約0.3sec movlw 3CH ;60 movwf CNTf BREATH3 call TIME5M decfsz CNTf, f goto BREATH3 ;消灯のまま約0.3secループ ; *** 徐々に光る:LCNTの間消灯、DCNTの間点灯(逆になる) *** movlw 0FFH movwf LCNT ;LCNT = 0FFH movlw 01H movwf DCNT ;DCNT = 01H BREATH4 bcf PORTA, 2 ;青消灯 movf LCNT, w movwf CNTf ;LCNTの値をワーキングカウンタにコピー(3) BREATH5 nop nop nop nop nop nop nop nop nop decfsz CNTf, f goto BREATH5 ;LCNTの回数ループ bsf PORTA, 2 ;青点灯 movf DCNT, w movwf CNTf ;DCNTの値をワーキングカウンタにコピー BREATH6 nop nop nop nop nop nop nop nop nop decfsz CNTf, f goto BREATH6 ;DCNTの回数ループ incf DCNT, f decfsz LCNT, f goto BREATH4 BREATH7 btfsc PORTB, 4 ;スロットルパルスがなくなるまで待つ goto BREATH7 goto MAIN1 ; ********************************* ;          巡航モード  ; ********************************* CRUISE movlw b'00000101' movwf PORTA ;青ON, 赤OFF goto MAIN1 ; ********************************* ;        怒りかけモード ; ********************************* GANGRY ; 入力:DCNT 0FH〜01H movlw b'00001101' movwf PORTA ;青ON, 赤ON movf DCNT, w sublw 10H ; W = 10H - DCNT (=01H 〜0FH) movwf LCNT ; L = W GANGRY0 movf LCNT, w movwf CNTf btfsc PORTB, 4 goto GANGRY3 ; シグナルがあったらループから抜ける movlw b'00001001' movwf PORTA ;青OFF, 赤ON GANGRY1 btfsc PORTB, 4 goto GANGRY3 ; シグナルがあったらループから抜ける decfsz CNTf, f goto GANGRY1 movf DCNT, w movwf CNTf btfsc PORTB, 4 goto GANGRY3 ; シグナルがあったらループから抜ける movlw b'00000101' movwf PORTA ;青ON, 赤OFF GANGRY2 btfsc PORTB, 4 goto GANGRY3 ; シグナルがあったらループから抜ける decfsz CNTf, f goto GANGRY2 goto GANGRY0 GANGRY3 ; シグナルがあったので、一定時間高速点滅 ; 一定時間=ニュートラルポイント ;      +75%スロットルポイント ;  = 2982+6*NTPINT+62+870+6*HGPINT-6*NTPINT ;  = 3914 + 6*HGPINT ; (2) movlw 44H ;=68 movwf CNTg ;(4) GANGRY6 movf LCNT, w ;((1)) movwf CNTf movlw b'00001001' movwf PORTA ;青OFF, 赤ON((4)) GANGRY4 decfsz CNTf, f ;((ループ(計)3*16-2 = 46steps)) goto GANGRY4 movf DCNT, w movwf CNTf movlw b'00000101' movwf PORTA ;青ON, 赤OFF GANGRY5 decfsz CNTf, f goto GANGRY5 ;((54steps)) decfsz CNTg, f goto GANGRY6 ;(54+3)*68-1+4=3879 movf HGPINT, w movwf CNTf ;3881 GANGRY55 nop nop nop decfsz CNTf, f goto GANGRY55 ;3881+6*HGPINT-1 movlw 9H ;9回ループ movwf CNTf ;3882(あと32) GANGRY7 decfsz CNTf, f goto GANGRY7 ;3882+9*3-1=3908 movlw b'00001001' movwf PORTA ;青OFF, 赤ON (3910) ; ***シグナルがなければ巡航モードへ btfss PORTB, 4 goto CRUISE movlw 10H movwf DCNT ; DCNTを減算しながらスロットル開度を測る ; 1カウント= 17steps=6.8us 最大15カウント GANGRY8 ;(3914) decfsz DCNT, f goto GANGRY9 goto MAIN8 ;怒り100%へ GANGRY9 movlw 03H movwf CNTf ;(5) GANGRY95 decfsz CNTf, f goto GANGRY95 ;(13) nop ;(14) btfsc PORTB, 4 goto GANGRY8 goto GANGRY ; 怒りかけモード続行 ; ********************************* ;    セッティングモード ; ********************************* STNG clrf NTPINT clrf HGPINT ; ******** ニュートラルポイント ******** STNG0 call TIME5M ; 5ms待ち btfss PORTB, 5 ; SWがおされていたら戻る goto STNG0 call TIME5M call TIME5M btfss PORTB, 5 goto STNG0 ; SWがOFFであることを確認 bcf PORTA, 0 ; チェック用LED ON STNG1 btfsc PORTB, 5 ; SWがONになるまでループ goto STNG1 call TIME5M call TIME5M call TIME5M call TIME5M btfsc PORTB, 5 ; SWONを確認 goto STNG1 STNG2 btfss PORTB, 4 ; シグナルがONになるまで待機 goto STNG2 nop nop btfss PORTB, 4 ;ノイズ対策 goto STNG2 ;(6 : 2.4us) ; 2982stepまで待つ(カウント開始点=1192.8us) call TIME1M ; 6+2+2553 = 2561 movlw 68H ;あと421 movwf CNTf STNG3 nop decfsz CNTf, F ;2+4*104-1=417 goto STNG3 ;2561+417 = 2978 nop nop btfss PORTB, 4 goto STNG7 ; high pointのセッティングへ(素通りで2982) STNG4 incfsz NTPINT, f ; NTPINTカウントアップ goto STNG5 goto STNG6 ; オーバーフローしたらNTPINT=FFにしてhighpointへ STNG5 btfsc PORTB, 4 ; signalが0(OFF)だったら次をスキップ goto STNG4 ; 6stepsでカウントアップ続行 goto STNG7 ; SW OFFなのでハイポイントのセッティングへ STNG6 ; NTPINTオーバーフロー処理 clrf NTPINT decf NTPINT, f ; NTPINT = 0FFH ; ******** ハイポイント ******** STNG7 ; highpoint  ; SWOFF確認、SWON検知、パルス幅測定 call TIME5M ; 5ms待ち btfss PORTB, 5 ; SWがおされていたら戻る goto STNG7 call TIME5M call TIME5M btfss PORTB, 5 goto STNG7 ; SWがOFFであることを確認 bsf PORTA, 0 ; チェック用LED OFF STNG8 btfsc PORTB, 5 ; SWがONになるまでループ goto STNG8 call TIME5M call TIME5M call TIME5M call TIME5M btfsc PORTB, 5 ; SWONを確認 goto STNG8 STNG9 btfss PORTB, 4 ; シグナルがONになるまで待機 goto STNG9 nop nop btfss PORTB, 4 ;ノイズ対策 goto STNG9 ;(6 : 2.4us) ; 4232stepまで待つ(カウント開始点=1692.8us) call TIME1M ; 6+2+2553 = 2561 call TIME100 ; +2+250 = 2813 call TIME100 ; +2+250 = 3065 call TIME100 ; +2+250 = 3317 call TIME100 ; +2+250 = 3569 call TIME100 ; +2+250 = 3821 call TIME100 ; +2+250 = 4037 あと195 movlw 30H ; カウント = 48 movwf CNTf STNG10 nop decfsz CNTf, F ;2+4*48-1=193 goto STNG10 ;4037+193 = 4230 btfss PORTB, 4 goto STNG14 ; セッティング終了へ(素通りで4232) STNG11 incfsz HGPINT, f ; HGPINTカウントアップ goto STNG12 goto STNG13 ; オーバーフローしたらHGPINT=FFにして終了へ STNG12 btfsc PORTB, 4 ; Signalが0(OFF)だったら次をスキップ goto STNG11 ; 6stepsでカウントアップ続行 goto STNG14 ; SW OFFなのでセッティング終了へ STNG13 ; HGPINTオーバーフロー処理 clrf HGPINT decf HGPINT, f ; HGPINT = 0FFH STNG14 movf NTPINT, w movwf E_DATA clrf E_ADRS call EEPWR movf HGPINT, w movwf E_DATA incf E_ADRS, f call EEPWR STING15 ; LED点滅無限ループ bcf PORTA, 0 ; チェック用LED ON call TIM1S bsf PORTA, 0 ; チェック用LED ON call TIM1S goto STING15 ; 無限ループ ; *************************************** ;    EEPROM書きこみサブルーチン ;     入力値:E_ADRS, E_DATA ; *************************************** EEPWR BCF STATUS,RP0 ; page 0 MOVF E_ADRS,W MOVWF EEADR MOVF E_DATA,W MOVWF EEDATA BSF STATUS,RP0 BSF EECON1,WREN MOVLW 55H MOVWF EECON2 MOVLW 0AAH MOVWF EECON2 BSF EECON1,WR ;-9 CALL TIME5M CALL TIME5M CALL TIME5M CALL TIME5M ;+25255*4=101011 BTFSC EECON1,WR GOTO ERRORWR ;書きこみ終了してなかったらエラー処理 BCF STATUS,RP0 return ERRORWR ; エラーの場合 bcf PORTA, 0 ; チェック用LED ON goto ERRORWR ; 無限ループ ; *************************************** ;    EEPROM読みだしサブルーチン ; *************************************** EEPRD clrf EEADR ;アドレス=0 bsf STATUS, RP0 bsf EECON1, RD bcf STATUS, RP0 movf EEDATA, W ;Wレジスタにデータ取りだし movwf NTPINT ;NTPINT = ニュートラルポイント値 incf EEADR, f ;アドレス=1 bsf STATUS, RP0 bsf EECON1, RD bcf STATUS, RP0 movf EEDATA, W ;Wレジスタにデータ取りだし movwf HGPINT ;HGPINT = ハイポイント値 return ;********************************* ;   タイマーサブルーチン ; TIME10 :10usec ; TIME100 :100usec ; TIME1M :1msec ; TIME5M :5msec ; TIM1S :1sec ;********************************* TIME100 ;100usec MOVLW 8H MOVWF CNTa T_LP1 CALL TIME10 ;2+(2+25+3)*8-1=241 DECFSZ CNTa,F GOTO T_LP1 NOP NOP NOP NOP NOP NOP NOP RETURN ;250*0.4=100usec TIME10 ;10usec MOVLW 07H MOVWF CNTb T_LP2 DECFSZ CNTb,F ;2+3*7-1=22 GOTO T_LP2 NOP RETURN ;22+3=25, 25*0.4=10usec TIME1M ;1msec (approx.) MOVLW 0AH MOVWF CNTc T_LP3 CALL TIME100 ;2+(250+5)*10-1=2551 DECFSZ CNTc,F GOTO T_LP3 RETURN ;2553 (=1.021msec) TIME5M ;5msec(about) MOVLW 32H MOVWF CNTd T_LP4 CALL TIME100 ;2+(250+5)*50-1=12751 DECFSZ CNTd,F GOTO T_LP4 RETURN ;12753 (=5101.2usec) TIM1S MOVLW 0C8H ;set 200 MOVWF CNTe T_LP5 CALL TIME5M ;2+(12753+5)*200-1=2551601 DECFSZ CNTe,F GOTO T_LP5 RETURN ;2551603 (=1,020,641.2usec) END