;**********************
;加速度ロガーVer4(車速信号)
;**********************
; Ver1('07/05/28)
; Gsens_Ver2_5に車速信号入力を追加
; sp_clkが来たら車速データを取り込む仕様
;
; Ver3('07/06/23)
; Speedプログラム修正
; sp_clk待ち時間を最小に設定
;
; Ver4('07/06/25)
; Speedのカウント/ウエイトタイムプログラム修正
; Speed_Ver.2_3に対応
;
; Ver5('07/06/25)
; 車速データが実車速化されたので,Speedデータ受信プログラムを仮対応
; Speed_Ver.2_4に対応
;
; Ver11('07/07/02)
; 送信データでY軸データの4桁目(DEC)が0のものを削除
; 送信データで車速データの4桁目(DEC)が0のものを削除
;
; Ver12('07/07/03)
; サンプリング100msに調整
; ほぼ満足いくレベルに完成
; Speed_Ver.2_4に対応
;
; Ver12test('07/07/05)
; 車速パルスカウント16bitに対応して完成
; Speed_Ver.2_7kijunに対応
;
; Ver13('07/07/05)
; 実車速8bitに対応して完成
; オーバーフロー時の車速は過去データを使用する方法に変更
; Speed_Ver.2_8に対応
;
; Ver14('07/07/17)
; サンプリング周期100ms調整完了
; 加速度ロガー車速対応版完成
; Speed_Ver.2_9に対応
;
; 課題
; 車速送信データが200q/h以上のデータは削除したがいいかも
;**********************
;
;PIC16F84A:4MHz用(1cycle=1μs)
;
;電源を入れて,SW1を押すとデータ送信モード,SW2を押すとデータ計測モード
;SW両方押しで停止モード
;
;⇒データ計測モードSW2
; 計測開始,0.1secごとに**分間まで(メモリいっぱい使用)
; X下位,X上位,Y下位,Y上位の順に4バイトずつ書き込み
; 12000ポイント×4バイト=48000バイト
; 中断操作(ボタンを二つ1秒以上押す)まで繰り返す。
;
;⇒データ送信モードSW1
; 9600bps,8bit,1stopbit
; パリティなし,フロー制御なし
; SW1を押すと,テキストデータが順に流れてくる
;
;
;
; ピン・アサイン
; RA0 →CLK(ADコンバータ)
; RA1 →CS(ADコンバータ)
; RA2 ⇔EEPROM SDA
; RA3 →EEPROM SCLK
; RA4 ←SP_CLK(車速用PIC)
; RB0 ←SP_DATA(車速用PIC)
; RB1 →RS232C送信
; RB2 ←D-OUT(ADコンバータ)
; RB3 →D_IN(ADコンバータ)
; RB4 →SP_REQ車速要求信号(車速用PICへ)
; RB5 ←プッシュSW2;データ記録開始モード
; RB6 →LED(0でOFF,1でON)
; RB7 ←プッシュSW1;データ送信モード
;
;
;***************************************
LIST P=PIC16F84A
INCLUDE "P16F84A.INC"
;****************
; 変数レジスタ定義 0CH〜7FHが汎用レジスタ
;****************
;---------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
;---------RS-232C用--------
sendt equ 1FH ; RS232C通信ウエイト時間の調整用
bitw equ 20H ; 送信中ビット数のカウント
txdata equ 21H ; 送信データ(8バイト)格納用変数
;---------パルスカウント-----
xplsh equ 2AH ; X軸パルス・カウンタ上位
xplsl equ 2BH ; X軸パルス・カウンタ下位
yplsh equ 2CH ; Y軸パルス・カウンタ上位
yplsl equ 2DH ; Y軸パルス・カウンタ下位
datao5 equ 22H ; eeprom 書き込み用データの1バイト目
datao6 equ 23H ; eeprom 書き込み用データの2バイト目
;--------10進数変換用--------
hexh equ 31H ; 16進数上位
hexl equ 32H ; 16進数下位
decxhh equ 3CH ; 10進数・千の位
decxh equ 2EH ; 10進数・百の位
decxm equ 2FH ; 10進数・十の位
decxl equ 30H ; 10進数・一の位
decyhh equ 43H ; 10進数・千の位
decyh equ 44H ; 10進数・百の位
decym equ 45H ; 10進数・十の位
decyl equ 46H ; 10進数・一の位
decshh equ 47H ; 10進数・千の位
decsh equ 48H ; 10進数・百の位
decsm equ 49H ; 10進数・十の位
decsl equ 4AH ; 10進数・一の位
dechh equ 4BH ; 10進数・千の位
dech equ 4CH ; 10進数・百の位
decm equ 4DH ; 10進数・十の位
decl equ 4EH ; 10進数・一の位
;--------メイン・ルーチン用--------
stepl equ 33H ; ステップ数カウンタ下位(960分カウンタ)
steph equ 34H ; ステップ数カウンタ上位
OUTBUF equ 35H ;
INBUFH equ 36H ;
INBUFL equ 37H ;
COUNT equ 38H ;
COUNT2 equ 3BH ;
old_plsl equ 3DH ; 前回車速パルス下位
old_plsh equ 3EH ; 前回車速パルス上位
;**********ADコンバータ************
ADCS equ 0x02 ; chip select line A/D
plsl equ 40H ; 車速信号受信データ下位
plsh equ 41H ; 車速信号受信データ上位
countg equ 42H ; 汎用カウンタ
ch_cntl equ 26H ; アナログ入力CH切り替え
d_data1 equ 27H ; AD変換データ格納先
d_data2 equ 28H ; AD変換データ格納先
data_buf equ 29H ;
;*******************
;ビット定義など
;*******************
di equ 7 ; eeprom入力はeepromレジスタの7ビット目
do equ 6 ; eeprom出力はeepromレジスタの6ビット目
sdata equ 2 ; SDA接続ポートはRA2
sclk equ 3 ; SCL接続ポートはRA3
ackf equ 6 ; EEPROM警告LEDはRB4
btime equ D'31' ; RS232C通信速度設定用変数 9600bps@4MHz
; btime=((オシレータ周波数(Hz)/転送スピード(bps)/4)-10)/3
org 0
;**********************
; ポート・セット,初期化
;**********************
bsf STATUS,RP0 ; TRIS設定のためバンクを切り替える
movlw b'00010000' ; PORTA入出力設定:RA4を入力(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
;****************************
;メインルーチン
;****************************
; SWが押されたか監視,SW1(RB7)でデータ送信モード
; SW2(RB5)でデータ記録開始
; その間,LEDが400ms周期で点滅
MENU1
movlw 0C8H ; カウンタを200にセット
movwf counte
bsf PORTB,6 ; LED点灯
bcf PORTB,4 ; SP_REQ=RB4をLO(初期化)
MENU2
call WAIT_1M ; 1ms時間待ち
btfss PORTB,7 ; SW1が1(OFF)だったらスキップ
goto DATATR ; onだったらデータ送信モードへ
btfss PORTB,5 ; SW2が1(OFF)だったらスキップ
goto LOG ; onだったらデータ計測モードへ
decfsz counte,f
goto MENU2 ; 200回ループ
movlw 0C8H ; カウンタを200にセット
movwf counte
bcf PORTB,6 ; LED消灯
MENU3
call WAIT_1M ; 1ms時間待ち
btfss PORTB,7 ; SW1が1(OFF)だったらスキップ
goto DATATR ; onだったらデータ送信モードへ
btfss PORTB,5 ; SW2が1(OFF)だったらスキップ
goto LOG ; onだったらデータ計測モードへ
decfsz counte,f
goto MENU3 ; 200回ループ
goto MENU1
;********************************
; データ計測モード
;********************************
;**********初期化***********
LOG
movlw 060H ; ステップ・カウンタのリセット,計測可能時間の制限
movwf stepl ; 4バイト(65536(0000H))-12000ステップ(20分,1ステップ0.1s)
movlw 073H ; 1ずつ加算していき,0になったら記録終了
movwf steph
clrf addrl ; eeprom書き込みアドレスリセット
clrf addrh
;*******データ計測********
LOG0
call Speed ; 車速データ受信
call Gmeas ; 加速度センサ・パルス計測
;*******データの記録********
movf xplsl,w ; X軸データを前ターン用変数にセット
movwf datao
movf xplsh,w
movwf datao2
movf yplsl,w ; Y軸データを前ターン用変数にセット
movwf datao3
movf yplsh,w
movwf datao4
movf plsl,w ; 車速データを前ターン用変数にセット
movwf datao5
movf plsh,w
movwf datao6
call EEPWT ;EEPROM書き込み
incfsz addrl,f ;書き込みアドレス+6加算,0なら次をスキップ
goto skip1
incf addrh,f
skip1
incfsz addrl,f
goto skip2
incf addrh,f
skip2
incfsz addrl,f
goto skip3
incf addrh,f
skip3
incfsz addrl,f
goto skip4
incf addrh,f
skip4
incfsz addrl,f
goto skip5
incf addrh,f
skip5
incfsz addrl,f
goto LOG2
incf addrh,f
;*******カウンタ処理*********
LOG2
incfsz stepl,f ;ステップカウンタ加算
goto LOG3
incfsz steph,f
goto LOG4
goto LOGend
LOG3
nop
nop
;*******SW入力(中断処理)********
LOG4
btfsc PORTB,7
goto LOG5
btfsc PORTB,5
goto LOG6
goto LOGend
LOG5
nop
nop
;********LED点滅**********
LOG6
bsf PORTB,6 ;LEDを10ms光らせる
movlw 00AH
movwf countc
LOG7
call WAIT_1M
decfsz countc,f
goto LOG7
bcf PORTB,6
;********時間あわせループ**********
; movlw 050H ;全体の計測時間の余りをここで消費する
; movwf countc ;50H=80回
;LOG8
; call WAIT_1M
; decfsz countc,f
; goto LOG8
; nop
goto LOG0
;********計測終了(中断)********
LOGend ; 記録終了:停止マーカ(7373H)を書き込む
call WAIT_50M ; EEPROMに書き込んだばかりなので少し待つ
movlw 073H
movwf datao
movwf datao2 ; 7373Hをセットして
movwf datao3
movwf datao4
movwf datao5
movwf datao6
call EEPWT ; EEPROM書き込み
bsf PORTB,6 ; LED1s点灯
call WAIT_500M
call WAIT_500M
bcf PORTB,6
goto MENU1
;********************************
; データ送信モード
;********************************
DATATR
movlw 060H ;計測モードの値にあわせること
movwf stepl
movlw 073H
movwf steph
clrf addrl
clrf addrh
DATATR1
call EEPRD ;X下位データ読み出し
movf datai,w
movwf hexl
incf addrl,f ; アドレス下位を+1加算
goto DATATR12 ; 繰り上がらなかったらDATATR12へジャンプ
incf addrh,f ; 上位繰上げ
DATATR12
call EEPRD ; X上位データ読み出し
movf datai,w
movwf hexh ; 10進変換用上位レジスタへ代入
; データが7373Hでないかチェック
movlw 073H
subwf hexh,w ; hexh-w→w
btfss STATUS,Z ; Zフラグが1だったら(=演算結果が0だったら)次をステップ
goto DATATR15
movlw 073H
subwf hexl,w ; hexl-w→w
btfss STATUS,Z ; Zフラグが1だったら(=演算結果が0だったら)次をステップ
goto DATATR15
; データが7373Hだった
goto DATATR3 ; 送信終了
DATATR15
incfsz addrl,f ; アドレス下位を+1加算
goto DATATR4 ; 繰り上がらなかったらDATATR4へジャンプ
incf addrh,f ; 上位繰上げ
DATATR4
call DECTR ; 10進変換ルーチン
movf dechh,w
movwf decxhh
movf dech,w
movwf decxh
movf decm,w
movwf decxm
movf decl,w
movwf decxl
call EEPRD ; Y下位データ読み出し
movf datai,w
movwf hexl ; 10進変換用下位レジスタへ代入
incf addrl,f ; アドレス下位を+1加算
goto DATATR13 ; 繰り上がらなかったらDATATR13へジャンプ
incf addrh,f ; 上位繰上げ
DATATR13
call EEPRD ; Y上位データ読み出し
movf datai,w
movwf hexh ; 10進変換用上位レジスタへ代入
incfsz addrl,f ; アドレス下位を+1加算
goto DATATR2 ; 繰り上がらなかったらDATATR2へジャンプ
incf addrh,f ; 上位繰上げ
DATATR2
call DECTR ; 10進変換ルーチン
movf dechh,w
movwf decyhh
movf dech,w
movwf decyh
movf decm,w
movwf decym
movf decl,w
movwf decyl
call EEPRD ; S下位データ読み出し
movf datai,w
movwf hexl ; 10進変換用下位レジスタへ代入
incf addrl,f ; アドレス下位を+1加算
goto DATATR14 ; 繰り上がらなかったらDATATR14へジャンプ
incf addrh,f ; 上位繰上げ
DATATR14
call EEPRD ; S上位データ読み出し
movf datai,w
movwf hexh ; 10進変換用上位レジスタへ代入
incfsz addrl,f ; アドレス下位を+1加算
goto DATATR16 ; 繰り上がらなかったらDATATR16へジャンプ
incf addrh,f ; 上位繰上げ
DATATR16
call DECTR ; 10進変換ルーチン
movf dechh,w ;
movwf decshh
movf dech,w
movwf decsh
movf decm,w
movwf decsm
movf decl,w
movwf decsl
CHECK_DEC0 ;バグ取りフィルタ
movf decyhh,w ;
btfsc STATUS,Z ;decyhh=0ならZフラグが1になっている。0なら次スキップ
goto DATATR33 ;Z=1なので読み出しをやめて,出力中止
movf decshh,w ;
btfss STATUS,Z ;decshh=0ならZフラグが1になっている。1なら次スキップ(千の位が0以外ってこと)
goto DATATR33 ;Z=0なので読み出しをやめて,出力中止
movlw "X"
movwf txdata ; 文字データを転送用変数に入れて
call RSTRANS ; RS232C出力ルーチン実行
movlw "," ; カンマで区切る
movwf txdata
call RSTRANS
movlw 030H ; ASCiiコードに変換(+30H)して
addwf decxhh,w
movwf txdata
call RSTRANS ; RS-232C送信
movlw 030H ; ASCiiコードに変換(+30H)して
addwf decxh,w
movwf txdata
call RSTRANS ; RS-232C送信
movlw 030H ; ASCiiコードに変換(+30H)して
addwf decxm,w
movwf txdata
call RSTRANS
movlw 030H ; ASCiiコードに変換(+30H)して
addwf decxl,w
movwf txdata
call RSTRANS
movlw "," ; カンマで区切る
movwf txdata
call RSTRANS
movlw "Y"
movwf txdata ; 文字データを転送用変数に入れて
call RSTRANS ; RS232C出力ルーチン実行
movlw "," ; カンマで区切る
movwf txdata
call RSTRANS
movlw 030H ; ASCiiコードに変換(+30H)して
addwf decyhh,w
movwf txdata
call RSTRANS ; RS-232C送信
movlw 030H ; ASCiiコードに変換(+30H)して
addwf decyh,w
movwf txdata
call RSTRANS ; RS-232C送信
movlw 030H ; ASCiiコードに変換(+30H)して
addwf decym,w
movwf txdata
call RSTRANS
movlw 030H ; ASCiiコードに変換(+30H)して
addwf decyl,w
movwf txdata
call RSTRANS
movlw "," ; カンマで区切る
movwf txdata
call RSTRANS
movlw "S"
movwf txdata ; 文字データを転送用変数に入れて
call RSTRANS ; RS232C出力ルーチン実行
movlw "," ; カンマで区切る
movwf txdata
call RSTRANS
movlw 030H ; ASCiiコードに変換(+30H)して
addwf decshh,w
movwf txdata
call RSTRANS ; RS-232C送信
movlw 030H ; ASCiiコードに変換(+30H)して
addwf decsh,w
movwf txdata
call RSTRANS ; RS-232C送信
movlw 030H ; ASCiiコードに変換(+30H)して
addwf decsm,w
movwf txdata
call RSTRANS
movlw 030H ; ASCiiコードに変換(+30H)して
addwf decsl,w
movwf txdata
call RSTRANS
movlw 00DH
movwf txdata
call RSTRANS
movlw 00AH ; 0D,0Aで「改行」
movwf txdata
call RSTRANS
DATATR33
bsf PORTB,6 ;確認用LED点滅
call WAIT_50M
bcf PORTB,6
call WAIT_50M
incfsz stepl,f ; ステップカウンタを加算
goto DATATR1 ; 繰上げがなかったらルーチン頭へジャンプ
incfsz steph,f ; カウンタ上位を加算
goto DATATR1 ; 繰上げがなかったらルーチン頭へジャンプ
DATATR3
bsf PORTB,6 ; 送信終了,LED点灯2s
call WAIT_500M
call WAIT_500M
call WAIT_500M
call WAIT_500M
bcf PORTB,6
goto MENU1
;*********************************
;RS-232C送信ルーチン
;txdataの値を送信
;*********************************
RSTRANS
bcf PORTB,1 ; スタートビット送信開始,送信ポートRB1をLOWに
movlw btime ; 転送中時間待ち用カウンタ
movwf sendt ; btimeはあらかじめ転送速度にあわせて定義しておく必要がある。
TRANS10
decfsz sendt,f
goto TRANS10 ; 転送速度(ここでは9600bps)に合わせて時間待ち
movlw 08H
movwf bitw ; 送信の単位は8ビットで1データ,bitwは8ビットカウント用変数
nop
TRANS0
rrf txdata,f ; txdata(送信データ)の最下位ビットをC(キャリ・ビット)に。
nop ; その他のビットはそれぞれ1桁ずつ下位の方(右側)にシフト。
btfss STATUS,C ; Cビットが1だったら送信ポートRB1をHighに,0だったらLowにする。
bcf PORTB,1 ; 下位ビット側から送信することになる。
btfsc STATUS,C
bsf PORTB,1
movlw btime
movwf sendt
TRANS11
decfsz sendt,f
goto TRANS11 ; 転送速度(ここでは9600bps)に合わせて時間待ち
decfsz bitw,f ; ビットカウントを1減らす
goto TRANS0 ; まだ8ビット送信していなかったら次のビットを送信
nop ;nopで時間調整
nop
nop
nop
nop
nop
bsf PORTB,1 ; 最後にストップビットを送信
movlw btime
movwf sendt
TRANS12
decfsz sendt,f ; ストップビット分ウエイト
goto TRANS12
return
;*****************************
;時間待ち用タイマサブルーチン
; 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
;******************************
;EEPROMデータ書き込みサブルーチン(1度に2バイト書き込む)
; アドレス:addrh,addrl
; データ : datao〜datao6
;******************************
EEPWT
call BSTART ; スタートビット発生
movlw b'10100000' ; コントロールバイト送信
movwf txbuf
call TX
movf addrh,w ; 書き込みアドレス上位を送信
movwf txbuf
call TX
movf addrl,w ; 書き込みアドレス下位を送信
movwf txbuf
call TX
movf datao,w ; X軸下位データバイトの1バイト目を送信
movwf txbuf
call TX
movf datao2,w ; X軸上位データバイトの2バイト目を送信
movwf txbuf
call TX
movf datao3,w ; Y軸下位データバイトの1バイト目を送信
movwf txbuf
call TX
movf datao4,w ; Y軸上位データバイトの2バイト目を送信
movwf txbuf
call TX
movf datao5,w ; 車速上位データバイトの2バイト目を送信
movwf txbuf
call TX
movf datao6,w ; 車速上位データバイトの2バイト目を送信
movwf txbuf
call TX
call BSTOP ; ストップビット発生,書き込み処理終了
return
;******************************
;EEPROMデータ読み込みサブルーチン
; アドレス:addrh,addrl
; データ : datai
;******************************
EEPRD
call BSTART ; スタートビット発生
movlw b'10100000' ; コントロールバイト送信(書き込みモード)
movwf txbuf
call TX
movf addrh,w ; 読み込みアドレス上位を送信
movwf txbuf
call TX
movf addrl,w ; 読み込みアドレス下位を送信
movwf txbuf
call TX
call BSTART ; スタートビット発生
movlw b'10100001' ; コントロールバイト送信(読み込みモード)
movwf txbuf
call TX
call RX
call BSTOP ; ストップビット発生
return
;*********バイトデータ送信サブルーチン*********
TX
movlw 008H
movwf count ; 1バイト=8ビット繰り返し用カウンタ
TXLP
bcf eeprom,do ; eeprom書き込み用ビットを0にしておく
btfsc txbuf,7 ; 書き込みデータは本当に0か?
bsf eeprom,do ; 書き込み用データが1だったので,書き込み用ビットを1にする
btfss eeprom,do ; 書き込み用データビットは1か?
goto bitlow
bsf PORTA,sdata ; 書き込み用ビットが1の場合:SDAをHighにする
goto clkout ; クロック操作へジャンプ
bitlow
bcf PORTA,sdata ; 書き込み用ビットが0の場合:SDAをLowにする
nop
clkout
bsf PORTA,sclk ; SCLをHighにする
nop
nop
nop
nop
bcf PORTA,sclk ; SCLをLowにする。ここまででビット書き込み完了
rlf txbuf,f ; 送信データバイトをシフトする
decfsz count,f ; 8ビット送信終わったか?
goto TXLP ; 終わるまでループ
;***ACKビット送信****
bsf eeprom,di ; eeprom読み込み用ビットを1にしておく
bsf STATUS,RP0
bsf TRISA,sdata ; SDAポートを入力にする
bcf STATUS,RP0
bsf PORTA,sclk ; SCLをHighにする
nop
nop
nop
nop
nop
btfss PORTA,sdata ; SDAポートからの入力をチェック
bcf eeprom,di ; ポートがLowの場合,読み込みビットを0に変更
bcf PORTA,sclk ; SCLをLowにする。
nop
bsf STATUS,RP0
bcf TRISA,sdata ; SDAポートを出力にもどす
bcf STATUS,RP0
nop
btfsc eeprom,di ; 読み込みビットをチェックして失敗(1)していたら
bsf PORTB,ackf ; LEDを点灯する
return
;*******バイトデータ受信サブルーチン*********
RX
clrf datai ; 読み込み用レジスタのクリア
movlw .8 ; set#bits to 8
movwf count
bcf STATUS,0 ; キャリビットを0にする
RXLP
rlf datai,f ; 読み込み用レジ下を左シフト,最下位は0になる
bsf eeprom,di ; eeprom読み込み用ビットを1にする
bsf STATUS,RP0
bsf TRISA,sdata ; SDAポートを入力にする
bcf STATUS,RP0
bsf PORTA,sclk ; SCLをHighにする
nop
nop
nop
nop
nop
btfss PORTA,sdata ; SDAポートからの入力をチェック
bcf eeprom,di ; ポートがLowの場合,読み込みビットを0に変更
bcf PORTA,sclk ; SCLをLowにする。
nop
bsf STATUS,RP0
bcf TRISA,sdata ; SDAポートを出力にもどす
bcf STATUS,RP0
btfsc eeprom,di ; 読み込みビットが1だったら
bsf datai,0 ; 読み込みようレジスタの最下位を1にする
decfsz count,f ; 8ビット受信終わったか?
goto RXLP ; 終わるまでループ
;***ACKビット送信****
bsf eeprom,do ; ACK出力用ビットを1にする
bsf PORTA,sdata ; SDAポートをhighにする
bsf PORTA,sclk ; SCLをhighにする
nop
nop
nop
nop
bcf PORTA,sclk ; SCLをLowにする
return
;********スタートビット発生サブルーチン********
BSTART
bsf PORTA,sdata ; SDAポートをhighにする
nop
nop
nop
bsf PORTA,sclk ; SCLをhighにする
nop
nop
nop
bcf PORTA,sdata ; SDAポートをLowにする。SCLがHighの間にSDAがLowになるとスタートビットと認識される
nop
nop
nop
bcf PORTA,sclk ; SCLをLowにする
nop
nop
nop
nop
return
;********ストップビット発生サブルーチン********
BSTOP
bcf PORTA,sdata ; SDAポートをLowにする。
nop
nop
nop
bsf PORTA,sclk ; SCLをhighにする
nop
nop
nop
bsf PORTA,sdata ; SDAポートをhighにする。SCLがHighの間にSDAがHighになるとストップビットと認識される
nop
nop
nop
bcf PORTA,sclk ; SCLをLowにする
nop
nop
nop
nop
return
;***********************************************
;10進数に変換するルーチン
;16進データhexh(上位),hexl(下位)の値をdec4(万の位)〜dec0(一の位)に変換する。
;***********************************************
DECTR
clrf dechh
clrf dech
clrf decm
clrf decl
movf hexh,w ; 入力データが0でないか調べる
btfss STATUS,Z ; hexhが0だった場合,Zフラグが1になっている。
goto DEC4 ; hexh(上位データ)が0でなかったら処理開始へ
movf hexl,w ;hexhが0だったのでhexlをチェック
btfss STATUS,Z
goto DEC1 ; hexl(下位データ)が0でなかったら処理開始へ
return ; hexhもhexlも0だったので出力データ0のまま復帰
DEC4 ;hexhが0じゃなかったのでhexlをチェック
movf hexl,w
btfss STATUS,Z ;0だったら次スキップ
goto DEC1 ;hexlが0じゃないのでカウントアップ
goto DEC3 ;0だったのでhexh減算へ
DEC1
call DECUP ;10進データカウントアップ
decfsz hexl,f ;下位データが0でなかったら繰り返す
goto DEC1
DEC3
movf hexh,w ;上位データが0でないか調べる
btfsc STATUS,Z ; Z=0(結果が正)の場合,次をスキップ
goto DEC2 ; Z=1(結果が0)の場合,下位バイト処理へ
decf hexh,f ;hexhを減算して
goto DEC1 ;下位の減算を再開
DEC2
return ;上位も0になったので処理終了
;*******カウントアップサブルーチン****************
DECUP
incf decl,f
movf decl,w
sublw 00AH
btfss STATUS,Z
return
;*****2桁目カウントアップサブルーチン*****
clrf decl
incf decm,f
movf decm,w
sublw 00AH
btfss STATUS,Z
return
;*****3桁目カウントアップサブルーチン*****
clrf decm
incf dech,f
movf dech,w
sublw 00AH
btfss STATUS,Z
return
;*****4桁目カウントアップサブルーチン*****
clrf dech
incf dechh,f
movf dechh,w
sublw 00AH
btfss STATUS,Z
return
;*****4桁目もオーバーフロー*****
clrf dechh
return
;*********************************************
;加速度センサ・パルス計測サブルーチン
; 消費時間:50μs(50.004μs)
; データ :X軸xplsh(上位)xplsl(下位)
; :Y軸yplsh(上位)yplsl(下位)
; :単位10μs
;*********************************************
Gmeas
clrf xplsh
clrf xplsl
clrf yplsh
clrf yplsl
clrf OUTBUF ;reset output buffer
call x_ad_conv
call y_ad_conv
; call WAIT_50M ;100ms周期時間あわせ
return
;**********X軸のADコンバータ通信************
x_ad_conv
clrf INBUFH ;reset input buffer
clrf INBUFL
BEGIN_AD_X
bcf PORTA,1 ;CS=RA1をLO select A/D converter
bsf PORTB,3 ;D_IN=RB3がHI 開始ビット
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse
bcf PORTA,0 ;CLK=RA0をLO
bsf PORTB,3 ;D_IN=RB3がHI シングルエンド
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse
bcf PORTA,0 ;CLK=RA0をLO
bcf PORTB,3 ;D_IN=RB3がLO D2無視
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse
bcf PORTA,0 ;CLK=RA0をLO
bcf PORTB,3 ;D_IN=RB3がLO D1
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse
bcf PORTA,0 ;CLK=RA0をLO
bsf PORTB,3 ;D_IN=RB3がHI D0
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse
bcf PORTA,0 ;CLK=RA0をLO
call IN_DATA ;read data from A/D converter
bsf PORTA,1 ;CS=RA1をHI de-select A/D converter
movlw 00FH ;load MSB mask
andwf INBUFH,W ;mask out MSB’s and put result in W
movwf xplsh ;output MSB’s
movf INBUFL,W ;load LSB’s into W
movwf xplsl ;output LSB’s
return ;finished, return to caller
;**********Y軸のADコンバータ通信************
y_ad_conv
clrf INBUFH ;reset input buffer
clrf INBUFL
BEGIN_AD_Y
bcf PORTA,1 ;CS=RA1をLO select A/D converter
bsf PORTB,3 ;D_IN=RB3がHI 開始ビット
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse
bcf PORTA,0 ;CLK=RA0をLO
bsf PORTB,3 ;D_IN=RB3がHI シングルエンド
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse
bcf PORTA,0 ;CLK=RA0をLO
bcf PORTB,3 ;D_IN=RB3がLO D2
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse
bcf PORTA,0 ;CLK=RA0をLO
bcf PORTB,3 ;D_IN=RB3がLO D1
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse
bcf PORTA,0 ;CLK=RA0をLO
bcf PORTB,3 ;D_IN=RB3がLO D0
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse
bcf PORTA,0 ;CLK=RA0をLO
call IN_DATA ;read data from A/D converter
bsf PORTA,1 ;CS=RA1をHI de-select A/D converter
movlw 0FH ;load MSB mask
andwf INBUFH,W ;mask out MSB’s and put result in W
movwf yplsh ;output MSB’s
movf INBUFL,W ;load LSB’s into W
movwf yplsl ;output LSB’s
return ;finished, return to caller
;**********ADコンバータ共通************
OUT_CONTROL
movlw 04H
movwf COUNT ;init bit counter
bsf PORTB,3 ;D_IN=RB3がHI 開始ビット
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse
bcf PORTA,0 ;CLK=RA0をLO
BIT_OUT
rlf OUTBUF,W ;rotate bit into carry
movwf OUTBUF
bcf PORTB,3 ;D_IN=RB3がLO pre-clear data out
btfsc STATUS,C ;check if bit should be set
bsf PORTB,3 ;D_IN=RB3がHI set data out
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse
bcf PORTA,0 ;CLK=RA0をLO
decfsz COUNT ;decrement bit counter
goto BIT_OUT ;output next bit
return ;finished, return to caller
IN_DATA
clrf INBUFL
clrf INBUFH ;reset input buffer
movlw 0DH
movwf COUNT ;init bit counter
bsf PORTA,0 ;CLK=RA0をHI 1サイクル待ち(前回のLOと合計して1.5サイクル)
bcf PORTA,0 ;CLK=RA0をLO
BIT_IN
bsf PORTA,0 ;CLK=RA0をHI set clock to latch bit
bcf STATUS,C ;pre-clear carry
btfsc PORTB,2 ;D_OUT=RB2を check for high or low bit
bsf STATUS,C ;set carry bit
rlf INBUFL,f
rlf INBUFH,f ;rotate bit into position
bcf PORTA,0 ;CLK=RA0をLO drop clock for next bit
decfsz COUNT ;decrement bit counter
goto BIT_IN ;get next bit
return ;return to caller
;*********************************************
;車速データ受信サブルーチン
; データ:plsh(上位)plsl(下位)
; SP_CLK受信ポート=RA4
; SP_REQ送信ポート=RB4
; SP_DATA受信ポート=RB0
;*********************************************
Speed
movlw 08H ;実車速化に伴い8bit化
movwf countf ;init bit counter
bcf STATUS,C
bcf PORTB,4 ;SP_REQ=RB4をLO(初期化)
movlw 078H ;C423H=50210μs-DATATR時間220H544μS=C203H
movwf counte ;C203H/2(ワード数で約半分以下)=6978H
movlw 069H ;オーバーフロー用(0km/h判定)
movwf countg ;ただし,車速PICの返答時間までとし,残りの余りは別でWAIT処理する
clrf plsh
clrf plsl
clrf COUNT
SP_REQ1
btfss PORTA,4 ;SP_CLKがHIなら次をスキップ
goto WAIT_BEFOR ;LOなのでHIになるまで規定時間待つ
bsf PORTB,4 ;SP_REQ=RB4をHI,車速PICはDATATRに移行
;今はCLKはHI,車速応答はHI
SP_REQ2 ;車速PICはBIT_OUT_HI
btfsc PORTA,4 ;SP_CLKがLOなら次をスキップ
goto SP_REQ2 ;HIなのでLOになるまで待つ
;今はCLKはLO,車速応答はHI
btfsc PORTB,0 ;SP_DATAがLOなら次をスキップ
bsf STATUS,C ;set carry bit
rlf plsl,f ;車速受信結果格納
clrf plsh
bcf PORTB,4 ;SP_REQ=RB4をLO
CHECK ;今はCLKはLO,車速応答はLO
btfss PORTA,4 ;SP_CLKがHIなら次をスキップ
goto CHECK ;LOなのでHIになるまで待つ
bsf PORTB,4 ;SP_REQ=RB4をHI
decfsz countf ;decrement bit counter
goto SP_REQ2
bcf PORTB,4 ;SP_REQ=RB4をLO
;*********残りWaitTime消費*******
movf COUNT,w ;wait回数を引き算する
andlw 2 ;wait回数とカウントワード分
addwf counte,f
DOWN1
decfsz counte,f
goto DOWN1
movlw 0FFH
movwf counte
decfsz countg,f
goto DOWN1
;*********固定WaitTime消費*******
movlw 0ACH ;DATATR時間と同じ時間(544μs)をここで消費する
movwf counte ;220H-70H-4H=1ACh=428
movlw 001H ;データ転送時間を引き算する
movwf countg ;14ワード×8回=112ワード=70H
DOWN2
decfsz counte,f
goto DOWN2
movlw 0FFH
movwf counte
decfsz countg,f
goto DOWN2
movf plsh,w
movwf old_plsh
movf plsl,w
movwf old_plsl
return
WAIT_BEFOR
incf COUNT ;wait回数カウンタ
decfsz counte,f ;0になったら次をスキップ
goto SP_REQ1
movlw 0FFH
movwf counte
decfsz countg,f
goto SP_REQ1
;******0km/h処理*********
SPEED_ZERO ;カウントオーバフローなので前回のデータを使用する
movf old_plsh,w
movwf plsh
movf old_plsl,w
movwf plsl
return ;カウントオーバフローなので戻る
end