;******************************************************************** ; 回転数ロガープログラム ; PIC16F84(20MHz) ; ver 2.00 ; RA3 : 動作確認用LED 点灯0 消灯1 ; RA4 : センサ入力 明0 暗1 ; RB1 : SW ON 0 OFF 1 ; ワンサイクル 320.2052msec ; そのうち300msec間でパルスをカウント ;******************************************************************** LIST P=PIC16F84 INCLUDE "P16F84.INC" ;****************************** ; 変数レジスタ定義 ;****************************** DPDT EQU 0CH ;LCD output data DISLOW EQU 0DH ;表示カウンタ下位 DISHIGH EQU 0EH ;表示カウンタ上位 CNTa EQU 0FH ;タイマ用カウンタ CNTb EQU 10H CNTc EQU 11H CNTd EQU 12H CNTe EQU 13H WORK1 EQU 14H ;work TEMP EQU 15H ;tempolary work ZFLG EQU 16H ;zero supress flag LPCNT EQU 17H ;ループ(300ms)カウンタ PLCNT EQU 18H ;パルスカウンタ PREDL EQU 19H ;前サイクルでのセンサ明(0)暗(1) BINH EQU 1AH ;Binary counter upper LPCNT2 EQU 1BH ;ループカウンタ下位 E_ADRS EQU 1CH ;EEPROMのアドレス DISLOW2 EQU 1DH ;アドレス表示カウンタ下位 E_ADRS2 EQU 1EH ;10進数変換用カウンタ PLCNT2 EQU 1FH ;同上 CNTf EQU 20H ;タイマ用カウンタ ORG 0 ;******************************** ; メインプログラム ;******************************** ;*** 初期化 **** MAIN CALL PORT_INI ;Port A,B initialize CLRF PORTB ;all clear CALL LCD_INI ;Reset LCD MENU1 ;1秒間SWが押されたか監視、おされたら読み出しモードへ MOVLW 0C8H ;set 200 MOVWF CNTe T_LP8 CALL TIME5M ;2+(25253+5)*200-1=5051601 BTFSS PORTB,1 ;SWが1(off)だったらスキップ GOTO MDMENU ;onだったらメニューモードへ DECFSZ CNTe,F GOTO T_LP8 ;************************** ;    ログ書きこみモード ;************************** CALL LCD_CLR ;表示クリア MOVLW "L" CALL LCD_DATA MOVLW "o" CALL LCD_DATA MOVLW "g" CALL LCD_DATA MOVLW " " CALL LCD_DATA MOVLW "M" CALL LCD_DATA MOVLW "o" CALL LCD_DATA MOVLW "d" CALL LCD_DATA MOVLW "e" CALL LCD_DATA CALL TIM1S ;10秒待ち CALL TIM1S CALL TIM1S CALL TIM1S CALL TIM1S CALL TIM1S CALL TIM1S CALL TIM1S CALL TIM1S CALL TIM1S MOVLW " " CALL LCD_DATA MOVLW "G" CALL LCD_DATA MOVLW "o" CALL LCD_DATA MOVLW "!" CALL LCD_DATA CLRF E_ADRS MAIN0 MOVLW 0C4H MOVWF LPCNT ;60回ループでオーバーフローするように MOVLW 06H ;250回ループでオーバーフローするように MOVWF LPCNT2 CLRF PLCNT MAIN1 BTFSC PREDL,0 ;直前センサが0(明)だったら次をスキップ GOTO DARK ;直前センサが1(暗)だったらDARKへ ;***前回ループではマーカー内であった*** BTFSS PORTA,4 ;現在センサが1(暗)だったら次をスキップ GOTO CNT5 ;現在センサが0(明)だったらカウントへ NOP NOP BTFSS PORTA,4 ;同じ確認をもう二回(ノイズ対策) GOTO CNT9 NOP NOP BTFSS PORTA,4 GOTO CNT13 ;**回転マーカーが切れた** BSF PORTA,3 ;LED消灯 MOVLW 01H MOVWF PREDL GOTO CNT17 ;***前回ループはマーカー外であった*** DARK BTFSC PORTA,4 ;現在センサが0(明)だったら次をスキップ GOTO CNT6 ;現在センサが1(暗)だったらカウントへ NOP NOP BTFSC PORTA,4 ;同じ確認をもう二回(ノイズ対策) GOTO CNT10 NOP NOP BTFSC PORTA,4 GOTO CNT14 ;**回転マーカーを検出** BCF PORTA,3 ;LED点灯 (14) CLRF PREDL ;(15) INCFSZ PLCNT,F ;PLCNT+1,0だったら次をスキップ GOTO CNT18 OVPL DECF PLCNT,F ;PLCNTをFFに GOTO CNT20 CNT5 NOP CNT6 NOP NOP NOP CNT9 NOP CNT10 NOP NOP NOP CNT13 NOP CNT14 NOP NOP CNT16 NOP CNT17 NOP CNT18 NOP CNT19 NOP CNT20 NOP CNT21 CALL TIME10 ;21+2+50=73 INCFSZ LPCNT2,F ;ループカウンタ(下位)+1 GOTO MAIN2 ;ループカウンタ下位オーバーフロー 20us X 250 =5000usec INCFSZ LPCNT,F ;LPCNT+1 GOTO MAIN3 GOTO MAIN6 ;ループカウンター上位オーバーフロー MAIN3 MOVLW 06H ;ループカウンタ上位オーバーフローなしのとき MOVWF CNTb ;80 T_LP7 DECFSZ CNTb,F ;+3*6-1=17 GOTO T_LP7 NOP ;98 GOTO MAIN1 ;100 MAIN2 MOVLW 07H ;ループカウンタ下位オーバーフローなしのとき MOVWF CNTb ;78 T_LP6 DECFSZ CNTb,F ;+3*7-1=20 GOTO T_LP6 ;98 GOTO MAIN1 ;100 MAIN6 ;全ループオーバーフロー 300msec -21 BCF STATUS,RP0 ;EEPROMへ書き出し MOVF E_ADRS,W MOVWF EEADR MOVF PLCNT,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 INCF E_ADRS,F ;アドレスをひとつ進める MOVLW 040H ;040Hになったら終了 SUBWF E_ADRS,W BTFSC STATUS,Z ;演算結果が0でないならZ=0で次をスキップ GOTO MAIN4 GOTO MAIN0 ;カウントアップ続行 : ワンサイクル101021+ 5(MAIN0の分) ; +300msec =320.2052msec MAIN4 ;EEPROMフル CALL LCD_CLR ;表示クリア MOVLW "L" CALL LCD_DATA MOVLW "o" CALL LCD_DATA MOVLW "g" CALL LCD_DATA MOVLW " " CALL LCD_DATA MOVLW "c" CALL LCD_DATA MOVLW "o" CALL LCD_DATA MOVLW "m" CALL LCD_DATA MOVLW "p" CALL LCD_DATA MOVLW "l" CALL LCD_DATA MOVLW "e" CALL LCD_DATA MOVLW "t" CALL LCD_DATA MOVLW "e" CALL LCD_DATA MAIN5 GOTO MAIN5 ERRORWR ;EEPROMエラー BCF PORTA,3 ;LED点灯 GOTO ERRORWR ;************************************* ;   モードメニュー ;************************************* MDMENU CALL LCD_CLR ;表示クリア MOVLW "P" CALL LCD_DATA MOVLW "u" CALL LCD_DATA MOVLW "s" CALL LCD_DATA MOVLW "h" CALL LCD_DATA MOVLW "S" CALL LCD_DATA MOVLW "W" CALL LCD_DATA MOVLW ":" CALL LCD_DATA MOVLW "S" CALL LCD_DATA MOVLW "e" CALL LCD_DATA MOVLW "n" CALL LCD_DATA MOVLW "s" CALL LCD_DATA MOVLW "o" CALL LCD_DATA MOVLW "r" CALL LCD_DATA MOVLW "A" CALL LCD_DATA MOVLW "D" CALL LCD_DATA MOVLW "J" CALL LCD_DATA MOVLW 0C0H ;2 Line 0 colum CALL LCD_CMD MOVLW "W" CALL LCD_DATA MOVLW "a" CALL LCD_DATA MOVLW "i" CALL LCD_DATA MOVLW "t" CALL LCD_DATA MOVLW " " CALL LCD_DATA MOVLW " " CALL LCD_DATA MOVLW ":" CALL LCD_DATA MOVLW "L" CALL LCD_DATA MOVLW "o" CALL LCD_DATA MOVLW "g" CALL LCD_DATA MOVLW "R" CALL LCD_DATA MOVLW "e" CALL LCD_DATA MOVLW "a" CALL LCD_DATA MOVLW "d" CALL LCD_DATA CALL TIM1S ;************5秒間SW待ち*********************** MOVLW 05H ;5 X 1sec MOVWF CNTf MENU2 MOVLW 0C8H ; 200 X 5msec MOVWF CNTe T_LP9 CALL TIME5M ;2+(25253+5)*200-1=5051601 BTFSS PORTB,1 ;SWが1(off)だったらスキップ GOTO SENSOR ;onだったらセンサー調整モードへ DECFSZ CNTe,F GOTO T_LP9 DECFSZ CNTf,F GOTO MENU2 ;************************************* ; ログ読み出しモード ;************************************* LOGREAD CLRF E_ADRS LOGREAD1 MOVF E_ADRS,W MOVWF EEADR BSF STATUS,RP0 BSF EECON1,RD BCF STATUS,RP0 MOVF EEDATA,W ;Wレジスタにデータ取りだし MOVWF PLCNT ;PLCNTに取りだし CALL CONV ;PLCNTの10進数化 CALL CONV2 ;アドレスの10進数化 CALL LCD_CLR ;表示クリア CALL DISP ;データ表示 WTSW0 BTFSS PORTB,1 ;SWが1(off)だったらスキップ GOTO WTSW0 CALL TIME5M CALL TIME5M CALL TIME5M CALL TIME5M CALL TIME5M CALL TIME5M BTFSS PORTB,1 ;SWが1(off)だったらスキップ GOTO WTSW0 WTSW BTFSC PORTB,1 ;SWが0(on)だったらスキップ GOTO WTSW CALL TIME5M CALL TIME5M CALL TIME5M CALL TIME5M CALL TIME5M CALL TIME5M BTFSC PORTB,1 ;SWが0(on)だったらスキップ GOTO WTSW INCF E_ADRS,F ;アドレスを一つ進める MOVLW 040H SUBWF E_ADRS,W BTFSS STATUS,Z ;E_ADRSが40Hだったら(Z=1)次をスキップ GOTO LOGREAD1 CLRF E_ADRS GOTO LOGREAD1 ;************************************* ; バイナリからBCDへの変換 ; バイナリ-1と同時にBCD+1 ;************************************* ;********* データ用 *************** CONV CLRF DISLOW ;初期クリア CLRF DISHIGH MOVF PLCNT,W BTFSC STATUS,Z ;PLCNTが0でなかったら(Z=0)、次をスキップ RETURN ;0のままリターン MOVWF PLCNT2 COLP CALL DISUP ;BCD+1 DECFSZ PLCNT2,F ;バイナリ下位−1 GOTO COLP ;ゼロで無い RETURN ;全部ゼロで完了 ;********** アドレス用 ************** CONV2 CLRF DISLOW2 ;初期クリア MOVF E_ADRS,W BTFSC STATUS,Z ;E_ADRSが0でなかったら(Z=0)、次をスキップ RETURN ;0のままリターン MOVWF E_ADRS2 COLP2 CALL DISUP2 ;BCD+1 DECFSZ E_ADRS2,F ;バイナリ下位−1 GOTO COLP2 ;ゼロで無い RETURN ;全部ゼロで完了 ;************************************ ; 4桁BCDカウントアップサブルーチン ;************************************ DISUP INCF DISLOW,F ;1桁目+1 MOVF DISLOW,W ;1桁目オーバーフローチェック ANDLW 0FH ;下位4ビット SUBLW 0AH ;W-10 BTFSS STATUS,Z ;W=10か RETURN ;カウントアップ終了 ;*** 2桁目カウントアップ **** MOVF DISLOW,W ;再取り出し ANDLW 0F0H ;1桁目0セット ADDLW 010H ;2桁目カウントアップ MOVWF DISLOW ;更新 ANDLW 0F0H ;上位4ビット SUBLW 0A0H ;2桁目オーバーフロー BTFSS STATUS,Z RETURN ;終了 ;**** 3桁目カウントアップ **** CLRF DISLOW ;1,2桁目更新 INCF DISHIGH,F ;3桁目カウントアップ MOVF DISHIGH,W ANDLW 0FH ;下位4ビット SUBLW 0AH BTFSS STATUS,Z ;3桁目オーバーフロー? RETURN ;終了 ;**** 4桁目 **** MOVF DISHIGH,W ANDLW 0F0H ADDLW 010H MOVWF DISHIGH RETURN ;************************************ ; 2桁BCDカウントアップサブルーチン ;************************************ DISUP2 INCF DISLOW2,F ;1桁目+1 MOVF DISLOW2,W ;1桁目オーバーフローチェック ANDLW 0FH ;下位4ビット SUBLW 0AH ;W-10 BTFSS STATUS,Z ;W=10か RETURN ;カウントアップ終了 ;*** 2桁目カウントアップ **** MOVF DISLOW2,W ;再取り出し ANDLW 0F0H ;1桁目0セット ADDLW 010H ;2桁目カウントアップ MOVWF DISLOW2 ;更新 RETURN ;終了 ;****************************************** ; データ表示サブルーチン ゼロサプレス付き ;***************************************** DISP MOVLW "T" CALL LCD_DATA MOVLW "i" CALL LCD_DATA MOVLW "m" CALL LCD_DATA MOVLW "e" CALL LCD_DATA MOVLW ":" CALL LCD_DATA MOVLW "C" CALL LCD_DATA MOVLW "o" CALL LCD_DATA MOVLW "u" CALL LCD_DATA MOVLW "n" CALL LCD_DATA MOVLW "t" CALL LCD_DATA MOVLW 0C0H ;2 Line 0 colum CALL LCD_CMD MOVLW 020H CALL LCD_DATA BCF ZFLG,0 ;reset zero flag MOVF DISLOW2,W BTFSC STATUS,Z ;DISLOW2が0じゃなかったら(Z=0)次をスキップ GOTO DSPAD0 ;DISLOW2が0だったらDSPAD0へ CALL DISP_D GOTO DSPDATA DSPAD0 MOVLW 020H CALL LCD_DATA MOVLW "0" CALL LCD_DATA DSPDATA MOVLW 020H CALL LCD_DATA MOVLW ":" CALL LCD_DATA MOVF PLCNT,W BTFSC STATUS,Z ;PLCNTが0じゃなかったら(Z=0)次をスキップ GOTO DSPDT0 ;DISLOW2が0だったらDSPAD0へ BCF ZFLG,0 ;reset zero flag MOVF DISHIGH,W CALL DISP_D ;display 1,2digits MOVF DISLOW,W CALL DISP_D ;display 3,4digits RETURN DSPDT0 MOVLW 020H CALL LCD_DATA MOVLW 020H CALL LCD_DATA MOVLW 020H CALL LCD_DATA MOVLW "0" CALL LCD_DATA RETURN ;**** 2桁BCD表示 ***** DISP_D MOVWF WORK1 ;一時保存 SWAPF WORK1,W ;桁入れ替え ANDLW 0FH ;上位だけ取り出し MOVWF TEMP ;一時保管 BTFSS ZFLG,0 ;既にゼロでないか? CALL ZEROSUP ;ゼロチェック MOVF TEMP,W SUBLW 0FH ;ゼロサプレスか? BTFSS STATUS,Z GOTO NUM1 ;サプレスしない MOVLW 020H ;ゼロサプレス GOTO DISP1 ;ブランク表示 ;**** 数字表示 **** NUM1 MOVF TEMP,W ;再取り出し IORLW 030H ;ASCIIコードに変換 ;**** 表示制御 **** DISP1 CALL LCD_DATA ;表示 ;**** 下位桁の表示 **** MOVF WORK1,W ;再取り出し ANDLW 0FH ;下位桁取り出し MOVWF TEMP ;一時保管 BTFSS ZFLG,0 ;既にゼロでないか? CALL ZEROSUP ;ゼロチェック MOVF TEMP,W ; SUBLW 0FH ;再取り出し BTFSS STATUS,Z ;ゼロサプレスか? GOTO NUM2 ;数字表示へ MOVLW 020H ;ゼロサプレス GOTO DISP2 ;**** 数字表示 **** NUM2 MOVF TEMP,W IORLW 030H ;ASCIIコードに変換 DISP2 CALL LCD_DATA ;表示 RETURN ;**** ゼロチェック、ゼロのときOFを返す **** ZEROSUP ANDLW 0FH ;check zero BTFSS STATUS,Z GOTO ZEND ;not zero MOVLW 0FH MOVWF TEMP ;set blank BCF ZFLG,0 ;zero flag off RETURN ZEND BSF ZFLG,0 ;not zero flag on MOVF TEMP,W RETURN ;*************************************************** ;  センサー調整モード ;*************************************************** SENSOR CALL LCD_CLR ;表示クリア MOVLW "S" CALL LCD_DATA MOVLW "e" CALL LCD_DATA MOVLW "n" CALL LCD_DATA MOVLW "s" CALL LCD_DATA MOVLW "o" CALL LCD_DATA MOVLW "r" CALL LCD_DATA MOVLW " " CALL LCD_DATA MOVLW "A" CALL LCD_DATA MOVLW "d" CALL LCD_DATA MOVLW "j" CALL LCD_DATA MOVLW "." CALL LCD_DATA MOVLW "M" CALL LCD_DATA MOVLW "o" CALL LCD_DATA MOVLW "d" CALL LCD_DATA MOVLW "e" CALL LCD_DATA SENSOR2 BTFSS PORTA,4 ;現在センサが1(暗)だったら次をスキップ GOTO SENSOR3 BSF PORTA,3 ;LED消灯 GOTO SENSOR2 SENSOR3 BCF PORTA,3 ;LED点灯 GOTO SENSOR2 ;*************************************************** ; 液晶表示器制御サブルーチン ;*************************************************** ;**** 表示データ書込み **** LCD_DATA MOVWF DPDT ;save dat ANDLW 0F0H ;mask lower MOVWF PORTB BCF PORTA,1 ;R/W BSF PORTA,2 ;RS high BSF PORTA,0 ;E high BCF PORTA,0 ;E low SWAPF DPDT,W ;get data lower ANDLW 0F0H MOVWF PORTB BSF PORTA,0 BCF PORTA,0 CALL LCD_BUSY RETURN ;**** コマンドデータ出力 ***** LCD_CMD MOVWF DPDT ;save dat ANDLW 0F0H ;mask lower MOVWF PORTB BCF PORTA,1 ;R/W BCF PORTA,2 ;RS low BSF PORTA,0 ;E high BCF PORTA,0 ;E low SWAPF DPDT,W ;get data lower ANDLW 0F0H MOVWF PORTB BSF PORTA,0 BCF PORTA,0 CALL LCD_BUSY RETURN ;**** 表示クリアコマンド出力 **** LCD_CLR MOVLW 01H ;clear command CALL LCD_CMD RETURN ;**** 初期化 ***** LCD_INI CALL TIME5M ;wait MOVLW 030H ;Function set 8bits MOVWF PORTB BCF PORTA,1 ;R/W BCF PORTA,2 ;RS BSF PORTA,0 ;E high BCF PORTA,0 ;E low CALL TIME5M ;wait MOVLW 030H ;Function reset 8bits MOVWF PORTB BCF PORTA,1 ;R/W BCF PORTA,2 ;RS BSF PORTA,0 ;E high BCF PORTA,0 ;E low CALL TIME100 MOVLW 030H ;Function reset 8bits MOVWF PORTB BCF PORTA,1 BCF PORTA,2 BSF PORTA,0 BCF PORTA,0 CALL TIME100 MOVLW 020H ;Function set 4bits mode MOVWF PORTB ;under the 8bits mode BCF PORTA,1 BCF PORTA,2 BSF PORTA,0 BCF PORTA,0 CALL TIME100 ;From here 4bits mode MOVLW 02CH ;function DL=0 4bit mode CALL LCD_CMD MOVLW 08H ;Display off D=C=B=0 CALL LCD_CMD MOVLW 0CH ;Display on D=1 C=B=0 CALL LCD_CMD MOVLW 06H ;Entry I/D=1 S=0 CALL LCD_CMD RETURN ;**** ビジーチェック ************ LCD_BUSY CLRF DPDT BSF STATUS,RP0 ;Bank 1 BSF OPTION_REG,7 ;Turn off PORTB pull up MOVLW 0FEH ;PORTB input MOVWF TRISB BCF STATUS,RP0 ;Bank 0 BCF PORTA,2 ;RS low BSF PORTA,1 ;R/W high BSF PORTA,0 ;E high BCF PORTA,0 ;E low MOVF PORTB,W ;get upper ANDLW 0F0H ;Mask out lower MOVWF DPDT BSF PORTA,0 ;E high BCF PORTA,0 ;E low MOVF PORTB,W ;get lower ANDLW 0FH ;Mask out upper IORWF DPDT,F ;upper+lower BTFSC DPDT,7 ;BUSY flag check GOTO LCD_BUSY ;retry BCF PORTA,1 ;R/W low BSF STATUS,RP0 ;Bank 1 MOVLW 0EH ;RB1,2,3 input MOVWF TRISB ;PORTB BCF STATUS,RP0 ;Bank 0 RETURN ;************************************ ; 入出力ピンモード初期化サブルーチン ;************************************ PORT_INI BSF STATUS,RP0 ;Set page 1 MOVLW 0EH ;RB1,2,3 input MOVWF TRISB ;PortB set MOVLW 010H ;only RA4 input MOVWF TRISA ;PortA set BCF STATUS,RP0 ;Set Page 0 RETURN ;********************************* ; タイマーサブルーチン ; TIME10 :10usec ; TIME100 :100usec ; TIME1M :1msec ; TIME5M :5msec ; TIM1S :1sec ;********************************* TIME100 ;100usec MOVLW 9H MOVWF CNTa T_LP1 CALL TIME10 ;2+(2+50+3)*9-1=496 DECFSZ CNTa,F GOTO T_LP1 NOP NOP RETURN ;500*0.2=100usec TIME10 ;10usec MOVLW 0FH MOVWF CNTb T_LP2 DECFSZ CNTb,F ;2+3*15-1=46 GOTO T_LP2 NOP NOP RETURN ;46+4=50, 50*0.2=10usec TIME1M ;1msec (approx.) MOVLW 0AH MOVWF CNTc T_LP3 CALL TIME100 ;2+(500+5)*10-1=5051 DECFSZ CNTc,F GOTO T_LP3 RETURN ;5053 (=1.0106msec) TIME5M ;5msec(about) MOVLW 32H MOVWF CNTd T_LP4 CALL TIME100 ;2+(500+5)*50-1=25251 DECFSZ CNTd,F GOTO T_LP4 RETURN ;25253 (=5050.6usec) TIM1S MOVLW 0C8H ;set 200 MOVWF CNTe T_LP5 CALL TIME5M ;2+(25253+5)*200-1=5051601 DECFSZ CNTe,F GOTO T_LP5 RETURN ;5051603 (=1,010,320.6usec) END