;********************** ;加速度ロガー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