;********************** ;車速計Ver.2 ;********************** ; Ver2('07/06/19) ; パルス間の時間を40μsごとにカウントする ; 50ms間メインPICに出力 ; ; Ver3('07/06/23) ; 車速応答(RB7)待ち時間を長めに調整 ; ; Ver4('07/06/25) ; 車速カウントを速度に演算するプログラムを追加 ; Gsen_Ver4_5に対応 ; ; Ver5('07/07/03) ; 10進化ルーチン修正 ; ; Ver6kijun('07/07/04) ; FGで車速計測間隔調整済み ; ; Ver7kijun('07/07/04) ; FGで車速カウントプログラム完成 ; ; Ver8('07/07/05) ; 車速の10進化とメインPICの8bit対応とフィルタ追加 ; Gsen_Ver4_13に対応 ; ; Ver9('07/07/17) ; 車速調整完了 ; Gsen_Ver4_14に対応 ;********************** ; ;PIC16F84A:4MHz用(1cycle=1μs) ; ;MR-SはエンジンECUから4パルスで出力される ;60km/h=637rpm=2548パルス/min,42.5パルス/s ; ; Gsens_Ver4と組み合わせて使用する ; Gsens_Ver4に50ms間出力信号を出し,応答信号がきたら,そのときの車速データを出力する ; ; ; ピン・アサイン ; RA0 →CLK(メインPICへ) ; RA1 → ; RA2 ⇔ ; RA3 →LED ; RA4 ; RB0 ← ; RB1 →車速データ送信(メインPICへ) ; RB2 ←車速信号入力 ; RB3 → ; RB4 ; RB5 ← ; RB6 → ; RB7 ←車速応答信号入力(メインPICから) ; ; ;*************************************** LIST P=PIC16F84A INCLUDE "P16F84A.INC" ;**************** ; 変数レジスタ定義 ;**************** ;---------EEPROM関連---------- ;eeprom equ 0CH ; eeprom ビット書き込み/読み込み用レジスタ ;addrl equ 0EH ; eeprom アドレス(下位) ;addrh equ 0FH ; eeprom アドレス(上位) ;datai equ 10H ; eeprom 読み込み用データ ;datao equ 11H ; eeprom 書き込み用データの1バイト目 ;datao2 equ 12H ; eeprom 書き込み用データの2バイト目 ;datao3 equ 13H ; eeprom 書き込み用データの1バイト目 ;datao4 equ 14H ; eeprom 書き込み用データの2バイト目 ;txbuf equ 16H ; eeprom 変数受け渡し用 ;count equ 17H ; eeprom ビット・カウンタ ;--------時間待ちループ用---------- counta equ 19H ; 時間待ち用のカウンタ countb equ 1AH countc equ 1BH countd equ 1CH counte equ 1DH ; 汎用カウンタ countf equ 1EH countg equ 1FH counth equ 20H counti equ 21H ;---------パルスカウント----- SPplsh equ 2AH ; 車速パルス・カウンタ上位 SPplsl equ 2BH ; 車速パルス・カウンタ下位 spsig equ 2CH ; Y軸パルス・カウンタ上位 spsigc equ 2DH ; Y軸パルス・カウンタ下位 plsh equ 22H ; パルス幅カウンタ上位 plsl equ 23H ; パルス幅カウンタ下位 ;--------10進数変換用-------- divl1 equ 31H ; 内部計算用1 divl2 equ 32H ; 内部計算用2 div1a equ 2EH ; 基準時間下位 div1b equ 2FH ; 基準時間上位 div2a equ 30H ; 割る数下位8bit div2b equ 33H ; 割る数上位8bit div3a equ 34H ; 答え下位 div3b equ 35H ; 答え上位 div4a equ 36H ; 余り下位 div4b equ 37H ; 余り上位 diverr equ 38H ; エラー ;COUNT2 equ 3BH ; ;dechh equ 3CH ; 10進数・千の位 ;int2h equ 3DH ; 1分間パルス積算上位 ;int2l equ 3EH ; 1分間パルス積算下位 ;**********ADコンバータ************ ;ADCS equ 0x02 ; chip select line A/D ;PCLATH equ 40H ; for Page0 operation ;SSPCON equ 41H ; for Bank0 operation ;FSR equ 42H ; ;ch_cntl equ 26H ; アナログ入力CH切り替え ;d_data equ 27H ; AD変換データ格納先 ;d_data2 equ 28H ; AD変換データ格納先 COUNT equ 29H ; ;******************* ;ビット定義など ;******************* org 0 ;********************** ; ポート・セット,初期化 ;********************** bsf STATUS,RP0 ; TRIS設定のためバンクを切り替える movlw b'00000000' ; PORTA入出力設定:入力(1),ほかは出力(0)に設定 movwf TRISA movlw b'10100101' ; PORTB入出力設定:RB0,RB2,RB5,RB7が入力(1),ほかは出力(0)に設定 movwf TRISB bcf STATUS,RP0 ; TRIS設定が終了したのでバンクを元にもどす movlw b'00000010' ; PORTA初期化(5V=1,0V=0) movwf PORTA movlw b'00000010' ; PORTB初期化(5V=1,0V=0) movwf PORTB ;**************************** ;メインルーチン ;**************************** ; 別PICからの要求(車速要求)がRB7=HIでデータ送信モード ; 車速信号(RB2)のパルス幅をカウント ; 車速送信(RB1) MENU1 call sp_data ; 車速カウントルーチンへ call cal_palus ; 実車速計算へ MENU4 movlw 080H ;13880H=80000μs movwf counte ;オーバーフロー用(0km/h判定) movlw 038H movwf countf movlw 001H movwf counti MENU2 bsf PORTA,0 ;CLK=RA0をHI generate clock pulse btfss PORTB,7 ;車速応答=RB7がHIなら次をスキップ goto MENU3 call DATATR ; HI(1)だったらデータ送信モードへ goto MENU1 MENU3 ;応答がないので待ち decfsz counte,f ;0になったら次をスキップ goto MENU2 movlw 0FFH ; movwf counte ; decfsz countf,f ; goto MENU2 movlw 0FFH ; movwf countf ; decfsz counti,f ; goto MENU2 bcf PORTA,0 ;CLK=RA0をLO nop goto MENU1 ;******************************** ; 車速カウントルーチン ;******************************** ;**********初期化*********** sp_data bcf PORTA,3 ;LEDを消灯(点いている場合があるので) clrf plsh clrf plsl ; movlw 001H ;車速がLOのとき1回待つ ; movwf countg ; clrf countd ;パルスカウント実行フラグ(0=初回,1=実行済み) movlw 0B3H ;22H*B3H=8850回(4km/h),オーバーフロー用(0km/h判定) movwf counte ; movlw 022H ; movwf countc ; ; movlw 00AH ; ; movwf countf ; ;*******データ計測******** sp_check btfsc PORTB,2 ;車速信号=RB2はLO(0)か? goto first_hilo ;HIなのでloを待ってからカウント goto first_lohi ;LOなのでhiを待ってからカウント ; decfsz countg,f ;0になったら次をスキップ ; goto sp_check ; goto SPEED_ZERO ;LOのままなので車速0と判断 SP_STOP nop bsf PORTA,3 ; 確認用LED点灯 call WAIT_1M bcf PORTA,3 call WAIT_1M return ;--------------------------------------------------------------------------------------- ;設定車速パルス間のカウンター(SP_cnt*は40us) ;パルス取得〜終了までのカウント ;------------------------------------- first_lohi btfss PORTB,2 ; 車速信号=RB2はHI(1)か?; 車速信号有→次スキップ、無→SP_cnt1 goto SP_cnt00 ;オーバーフローダウン goto SP_cnt1 SP_cnt00 decfsz counte,f ;0になったら次をスキップ goto first_lohi movlw 0FFH ; movwf counte ; decfsz countc,f ;0になったら次をスキップ goto first_lohi ; movlw 0FFH ; ; movwf countc ; ; decfsz countf,f ;0になったら次をスキップ ; goto SP_cnt11 ; btfsc countd,0 ; パルスカウント済み(0ビットが1)なら車速0処理へ,未実行(0)ならLOカウントへ goto SPEED_ZERO ; LOカウントを実行済み(1)なのでSEED_ZERO処理へ ;======LOからHIになるのを待ってからカウント開始のパターン======== SP_cnt1 decfsz counte,f ;0になったら次をスキップ goto SP_cnt11 movlw 0FFH ; movwf counte ; decfsz countc,f ;0になったら次をスキップ goto SP_cnt11 ; movlw 0FFH ; ; movwf countc ; ; decfsz countf,f ;0になったら次をスキップ ; goto SP_cnt11 ; btfsc countd,0 ; パルスカウント済み(0ビットが1)なら車速0処理へ,未実行(0)ならLOカウントへ goto SPEED_ZERO ; LOカウントを実行済み(1)なのでSEED_ZERO処理へ ; incf countd,f ; カウント実行フラグを1 ; goto SP_cnt2 ; LOカウントへ SP_cnt11 call COUNT_UP ; HIパルス時間をカウント call wait40us_4MHz ; 40us待機(実質call〜ret=27us) btfsc PORTB,2 ; 車速信号=RB2はLO(0)か?; 車速信号有→次スキップ、無→SP_cnt1 goto SP_cnt1 ; btfsc countd,0 ; パルスカウント済み(0ビットが1)なら終了処理へ,未実行(0)ならLOカウントへ ; goto SP_STOP ; LOカウントを実行済み(1)なので終了処理へ ; incf countd,f ; カウント実行フラグを1 goto SP_cnt2 ; LOカウントへ ;パルス終了〜取得までのカウント SP_cnt2 decfsz counte,f ;0になったら次をスキップ goto SP_cnt12 movlw 0FFH ; movwf counte ; decfsz countc,f ;0になったら次をスキップ goto SP_cnt12 ; movlw 0FFH ; ; movwf countc ; ; decfsz countf,f ;0になったら次をスキップ ; goto SP_cnt12 ; btfsc countd,0 ; パルスカウント済み(0ビットが1)なら車速0処理へ,未実行(0)ならHIカウントへ goto SPEED_ZERO ; HIカウントを実行済み(1)なのでSEED_ZERO処理へ ; incf countd,f ; カウント実行フラグを1 ; goto SP_cnt1 ; HIカウントへ SP_cnt12 call COUNT_UP ; LOパルス時間をカウント call wait40us_4MHz ; 40us待機(実質call〜ret=27us) btfss PORTB,2 ; 車速信号=RB2はHI(1)か?; 車速信号有→次スキップ、無→SP_cnt2 goto SP_cnt2 ; btfsc countd,0 ; パルスカウント済み(0ビットが1)なら終了処理へ,未実行(0)ならHIカウントへ goto SP_STOP ; HIカウントを実行済み(1)なので終了処理へ ; incf countd,f ; カウント実行フラグを1 ; goto SP_cnt1 ; HIカウントへ ;======HIからLOになるのを待ってからカウント開始のパターン======== first_hilo btfsc PORTB,2 ; 車速信号=RB2はLO(0)か?; 車速信号有→SP_cnt01、無→次スキップ goto SP_cnt01 ;オーバーフローダウン goto SP_cnt20 SP_cnt01 decfsz counte,f ;0になったら次をスキップ goto first_hilo movlw 0FFH ; movwf counte ; decfsz countc,f ;0になったら次をスキップ goto first_hilo ; movlw 0FFH ; ; movwf countc ; ; decfsz countf,f ;0になったら次をスキップ ; goto SP_cnt11 ; btfsc countd,0 ; パルスカウント済み(0ビットが1)なら車速0処理へ,未実行(0)ならLOカウントへ goto SPEED_ZERO ; LOカウントを実行済み(1)なのでSEED_ZERO処理へ ;パルス終了〜取得までのカウント SP_cnt20 decfsz counte,f ;0になったら次をスキップ goto SP_cnt21 movlw 0FFH ; movwf counte ; decfsz countc,f ;0になったら次をスキップ goto SP_cnt21 ; movlw 0FFH ; ; movwf countc ; ; decfsz countf,f ;0になったら次をスキップ ; goto SP_cnt12 ; btfsc countd,0 ; パルスカウント済み(0ビットが1)なら車速0処理へ,未実行(0)ならHIカウントへ goto SPEED_ZERO ; HIカウントを実行済み(1)なのでSEED_ZERO処理へ ; incf countd,f ; カウント実行フラグを1 ; goto SP_cnt1 ; HIカウントへ SP_cnt21 call COUNT_UP ; LOパルス時間をカウント call wait40us_4MHz ; 40us待機(実質call〜ret=10us) btfss PORTB,2 ; 車速信号=RB2はHI(1)か?; 車速信号有→次スキップ、無→SP_cnt20 goto SP_cnt20 ; btfsc countd,0 ; パルスカウント済み(0ビットが1)なら終了処理へ,未実行(0)ならHIカウントへ ; goto SP_STOP ; HIカウントを実行済み(1)なので終了処理へ ; incf countd,f ; カウント実行フラグを1 goto SP_cnt22 ; HIカウントへ SP_cnt22 decfsz counte,f ;0になったら次をスキップ goto SP_cnt23 movlw 0FFH ; movwf counte ; decfsz countc,f ;0になったら次をスキップ goto SP_cnt23 ; movlw 0FFH ; ; movwf countc ; ; decfsz countf,f ;0になったら次をスキップ ; goto SP_cnt11 ; btfsc countd,0 ; パルスカウント済み(0ビットが1)なら車速0処理へ,未実行(0)ならLOカウントへ goto SPEED_ZERO ; LOカウントを実行済み(1)なのでSEED_ZERO処理へ ; incf countd,f ; カウント実行フラグを1 ; goto SP_cnt2 ; LOカウントへ SP_cnt23 call COUNT_UP ; HIパルス時間をカウント call wait40us_4MHz ; 40us待機(実質call〜ret=27us) btfsc PORTB,2 ; 車速信号=RB2はLO(0)か?; 車速信号有→SP_cnt22、無→次スキップ goto SP_cnt22 ; btfsc countd,0 ; パルスカウント済み(0ビットが1)なら終了処理へ,未実行(0)ならLOカウントへ goto SP_STOP ; LOカウントを実行済み(1)なので終了処理へ ; incf countd,f ; カウント実行フラグを1 ; goto SP_cnt20 ; LOカウントへ ;-------------------------------------------------------------------------------- ;【 4MHz用】パルス測定タイマー(基準40usecのOFF時間) : 完成版(Call〜ret=27.0us) ;-------------------------------------------------------------------------------- wait40us_4MHz movlw 06H ;パルスカウント間隔はここでコントロール movwf counth W_LOOP5 decfsz counth,f ; 2+3*9-1=28 goto W_LOOP5 nop return ;******パルスカウント********* COUNT_UP incfsz plsl goto rtn incf plsh return rtn nop return ;******0km/h処理********* SPEED_ZERO clrf plsl clrf plsh goto SP_STOP ;******************************** ; データ送信モード ;******************************** DATATR movlw 08H movwf COUNT ;init bit counter ; movlw 92H ;確認用2282H=8850=4km/h ; movwf plsl ; movlw 22H ; movwf plsh BIT_OUT_HI ;今はCLKはHI,車速応答はHI rlf div3a,f ;rotate bit into carry ; rlf plsh,f ;rotate bit into carry bcf PORTB,1 ;車速出力=RB1を0(初期化) btfsc STATUS,C ;check if bit should be set bsf PORTB,1 ;車速出力=RB1を1 bcf PORTA,0 ;CLK=RA0をLO CHECK1 btfsc PORTB,7 ;車速応答=RB7がLOなら次をスキップ goto CHECK1 ;HIなのでLOになるまで待つ ;今はCLKはLO,車速応答はLO bsf PORTA,0 ;CLK=RA0をHI clk_check_HI btfss PORTB,7 ;車速要求=RB7がHIなら次をスキップ goto clk_check_HI ;LOなのでHIになるまで待つ ;今はCLKはHI,車速応答はHI decfsz COUNT ;decrement bit counter goto BIT_OUT_HI ;output next bit bcf PORTA,0 ;CLK=RA0をLO ;今はCLKはLO,車速応答はLO return ;finished, return to caller ; movlw 08H ; movwf COUNT ;init bit counter ;BIT_OUT_LO ;今はCLKはHI,車速応答はHI ; rlf plsl,f ;rotate bit into carry ; bcf PORTB,1 ;車速出力=RB1を0(初期化) ; btfsc STATUS,C ;check if bit should be set ; bsf PORTB,1 ;車速出力=RB1を1 ; bcf PORTA,0 ;CLK=RA0をLO ;CHECK2 ; btfsc PORTB,7 ;車速応答=RB7がLOなら次をスキップ ; goto CHECK2 ;HIなのでLOになるまで待つ ; ;今はCLKはLO,車速応答はLO ; bsf PORTA,0 ;CLK=RA0をHI ;clk_check_LO ; btfss PORTB,7 ;車速要求=RB7がHIなら次をスキップ ; goto clk_check_LO ;LOなのでHIになるまで待つ ; ;今はCLKはHI,車速応答はHI ; decfsz COUNT ;decrement bit counter ; goto BIT_OUT_LO ;output next bit ; bcf PORTA,0 ;CLK=RA0をLO ; ;今はCLKはLO,車速応答はLO ; return ;finished, return to caller ;***************************** ;時間待ち用タイマサブルーチン ; WAIT_100U :100μs ; WAIT_1M :1ms ; WAIT_50M :50ms ; WAIT_500M :0.5s ;***************************** WAIT_100U movlw 20H movwf counta W_LOOP1 decfsz counta,f ; 2+3*32-1=97 goto W_LOOP1 nop return ; 97+3=100(μs) WAIT_1M movlw 0AH ; 10回ループ movwf countb W_LOOP2 call WAIT_100U ; 2+(100+5)*10-1=1051 decfsz countb,f goto W_LOOP2 return ; 1051+2=1053(=1.053ms) WAIT_50M movlw 32H ; 50回ループ movwf countc W_LOOP3 call WAIT_1M decfsz countc,f goto W_LOOP3 return WAIT_500M movlw 0AH ; 10回ループ movwf countd W_LOOP4 call WAIT_50M decfsz countd,f goto W_LOOP4 return ;--------------------------------------------------------------------------------------- ; 16bitの割算 ; 車速パルス数から速度計算 cal_palus movlw 092H movwf div1b ;基準時間40us( HEX(927C) = DEC(37500) ) movlw 07CH movwf div1a movf plsh,w ; movlw 022H ;確認用2292H=8850パルス=4km/h movwf div2b ;割る数上位8bit movf plsl,w ; movlw 092H ;確認用 movwf div2a ;割る数下位8bit call div16 ;割算実施( 解 = div3b,a 余 = div4b,a ) return ;16bit割算 div16 movlw 10H ;10H=16 movwf divl1 ;内部計算用1 movf div2a,0 ;割る数下位8bit movwf div4a ;余り下位8bit movf div2b,0 ;割る数上位8bit movwf div4b ;余り上位8bit di1601 rlf div4a,1 ;1bit左シフト,余り下位 rlf div4b,1 ;1bit左シフト,余り上位 btfsc STATUS,C ;Cフラグ確認 goto di1602 ;割る数の上位ビット位置検索 decfsz divl1,1 ; goto di1601 ; movlw 1 ; movwf diverr ;割る数 = 0 → エラー return di1602 clrf div3a ;答え下位8bit,解セット用変数クリア clrf div3b ;答え上位8bit clrf div4a ;余り下位8bit,ワーク用変数クリア clrf div4b ;余り上位8bit movlw 10h ; movwf divl2 ;内部計算用2 movf divl1,0 ;内部計算用1 subwf divl2,1 ;残ループ数 di1603 bcf STATUS,C ;Cフラグ = 0 rlf div1a,1 ; rlf div1b,1 ; rlf div4a,1 ; rlf div4b,1 ; decfsz divl1,1 ;割られる数を初期位置までシフト goto di1603 ; di1604 ;現位置での減算が可否確認 movf div2b,0 ; subwf div4b,0 ; btfss STATUS,C ; goto di1606 ; movf div4b,0 ; subwf div2b,0 ; btfss STATUS,C ; goto di1605 ; movf div2a,0 ; subwf div4a,0 ; btfss STATUS,C ; goto di1606 ; di1605 movf div2a,0 ; subwf div4a,1 ;ワークから下位を引く btfss STATUS,C ;Cフラグ = 1 → skip decf div4b,1 ;上位 -1 movf div2b,0 ; subwf div4b,1 ;ワークから上位を引く bsf STATUS,C ;Cフラグ = 1 goto di1607 ; di1606 bcf STATUS,C ;Cフラグ = 0 di1607 rlf div3a,1 ;Cフラグの内容を解にシフト rlf div3b,1 ; movf divl2,1 ;divl2 = 0 の確認 btfsc STATUS,2 ;2bitは何のビットか後で確認すること goto di1608 ;最下位まで処理したなら終了 decf divl2,1 ;bit位置を1つ下げる(右へ) bcf STATUS,C ;Cフラグ = 0 rlf div1a,1 ;ワークへ1bit左シフト rlf div1b,1 ; rlf div4a,1 ; rlf div4b,1 ; goto di1604 ; di1608 clrf diverr ;正常終了 return end