kuroの覚え書き

96の個人的覚え書き

タコメータープログラムその後



内容を吟味して一から作成し直した。


LIST P=PIC16F84
INCLUDE "P16F84.INC"
;****************************************************
; 変数定義とレジスタ割付
;****************************************************

BYTE0 EQU 0DH ;周波数カウンタ0
BYTE1 EQU 0EH ;周波数カウンタ1
BYTE2 EQU 0FH ;周波数カウンタ2
DPDT EQU 10H ;液晶表示データ
FIGCNT EQU 15H ;
CNT1 EQU 16H ;タイマ用カウンタ
CNT2 EQU 17H
CNT3 EQU 18H
CNT4 EQU 19H
LPCNT1 EQU 1BH ;Loop Counter
LPCNT2 EQU 1CH ;Loop Counter
OVRFLW EQU 1DH ;Over Flow Flag
TEMP EQU 20H ;tempolary work

;********************************
; Jumping Vector
;********************************
ORG 0
GOTO MAIN

ORG 4
GOTO INTPROC
INTPROC RETURN

ORG 08H

;********************************
; Main Routine
;********************************

MAIN
BCF INTCON,GIE ;Interrupt Disable
BTFSC INTCON,GIE
GOTO $-2 ;retry BCF INTCON,GIE

CALL PORT_INI ;Port A,B initialize
CALL LCD_INI ;Reset LCD

MAINLP
CALL MEASURE
CALL LCD_CLR ;液晶表示器クリア
CALL DISP_DIGIT
; CALL DISP_OTHER
GOTO MAINLP

;********************************
;計測実行サブルーチン
;Vmaxのタコメーターパルスにあわせてゲートタイムは0.6秒
;PortAのRA4がゲート制御ピン
;10MHzオシレータ使用が前提
;********************************
MEASURE
BSF STATUS,RP0 ;Set page 1
MOVLW 068H ;set to no prescale
MOVWF OPTION_REG ;
BCF STATUS,RP0 ;Set Page 0
CLRF TMR0 ;カウンタリセット
BCF PORTA,4 ;ゲートを閉める

;**** ゲートタイム600msec *****
BSF PORTA,4 ;ゲートを開ける
CLRF OVRFLW ;OverFlowフラグをクリア
MOVLW 03H
MOVWF TEMP ;4STEP
LP1 CALL MESLOOP ;(249998STEP)
DECFSZ TEMP,F
GOTO LP1 ;250001*3-1STEP
CALL MESLOOP ;249998STEP
CALL MESLOOP ;249998STEP
CALL MESLOOP ;249998STEP
BCF PORTA,4 ;ゲートを閉める (250000*6)
RETURN

;**** 計測実行ループ(249,996steps) ****
MESLOOP MOVLW 08DH ;ループ繰り返しカウンタ=141
MOVWF LPCNT1
;++++++++++
MESLP1 MOVLW 088H ;第二カウンタ=136
MOVWF LPCNT2 ;
;***********
MESLP2 BTFSS INTCON,T0IF ;13 steps loop
GOTO DUMY1
BCF INTCON,T0IF ;T0IFフラグをリセット
MOVLW 1 ;カウント更新用定数
GOTO NEXT
DUMY1 NOP ;時間調整用NOP
NOP
MOVLW 0 ;カウンタ更新用定数
NEXT ADDWF BYTE1,F ;BYTE1+T0IF
RLF BYTE1,W ;carry to d<0>
ANDLW 1 ;キャリーだけ取り出し
ADDWF BYTE2,F ;BYTE2+Carry
DECFSZ LPCNT2,F ;ループ終了か?
GOTO MESLP2 ;
;**********
NOP
MESLP3 DECFSZ LPCNT1,F ;(13*LPCNT2+5)*LPCNT1
GOTO MESLP1 ;(13*136+5)*141=249993-1
;+++++++++++++++
RETURN ;+2+2=249996

;************************************
;バイナリから10進数へ変換後LCDに数字を表示するサブルーチン
;120カウントが最大値なので3桁しか表示しない
;************************************
DISP_DIGIT ;3桁に分けて各桁をカウント
MOVF TMR0,W ;TMR0をBYTE0に取出し
MOVWF BYTE0
CLRF FIGCNT ;FIGCNTをリセット
FIGLOOP100
MOVLW 064H ;100をロードして
SUBWF BYTE0,F ;元のデータから100を引く
BTFSC STATUS,C ;マイナスになるまで繰り返す
GOTO CNTPLUS100
GOTO ENDFIG100
CNTPLUS100
INCF FIGCNT,F ;100の位の数を数える
GOTO FIGLOOP100
ENDFIG100
MOVF FIGCNT,W
CALL DISP_NUM ;100の位の表示
MOVLW 064H ;100をロード
ADDWF BYTE0,F ;マイナスになったBYTE0をプラスに戻す
CLRF FIGCNT ;FIGCNTをリセット
FIGLOOP10
MOVLW 0AH ;10をロードして
SUBWF BYTE0,F ;データから10を引く
BTFSC STATUS,C ;マイナスになるまで繰り返す
GOTO CNTPLUS10
GOTO ENDFIG10
CNTPLUS10
INCF FIGCNT,F ;10の位の数を数える
GOTO FIGLOOP10
ENDFIG10
MOVF FIGCNT,W
CALL DISP_NUM ;10の位の表示
MOVLW 0AH ;10をロード
ADDWF BYTE0,W ;マイナスになったBYTE0をプラスに戻し、Wレジスタにロード
CALL DISP_NUM ;1の位の表示
RETURN
DISP_NUM ADDLW '0' ;ASCIIコードに変換
CALL LCD_DATA ;数字の表示
RETURN


;************************************
; PORT A & B Initialize Routine
;************************************

PORT_INI
BSF STATUS,RP0 ;Set page 1
MOVLW 0EH ;00001110 only RB1,2,3 input (RB3でhigh/low bandを切り替える事を想定)
MOVWF TRISB ;PortB set
MOVLW 018H ;00011000 only RA3,4 input
MOVWF TRISA ;PortA set
MOVLW 057H ;1010111 OPTION set TMR0=1:256
MOVWF OPTION_REG ;for TMR0
BCF STATUS,RP0 ;Set Page 0
CLRF PORTB ;all clear
RETURN

;************************************
;LCD制御サブルーチン
;************************************
;****LCD command out****
LCD_CMD
MOVWF DPDT ;Commandデータの一時保存
ANDLW 0F0H ;上位4ビットをまず出力
MOVWF PORTB ;RB4-7のデータバスへ出力
BCF PORTA,1 ;R/Wを0にセット Command条件セット
BCF PORTA,2 ;RSを0にセット
BSF PORTA,0 ;E high ストローブ信号出力
BCF PORTA,0 ;E low
SWAPF DPDT,W ;一時保存データの上位下位を入れ替え
ANDLW 0F0H ;下位4ビットを出力
MOVWF PORTB ;RB4-7へ出力
BSF PORTA,0 ;ストローブ信号出力
BCF PORTA,0
CALL LCD_BUSY ;Busy信号が無くなるまで待つ
RETURN
;**** LCD Data Write ****
LCD_DATA
MOVWF DPDT ;表示データ(ASCII)の一時保存
ANDLW 0F0H ;上位4ビット転送
MOVWF PORTB
BCF PORTA,1 ;R/Wを0にセット、データ送信モードセット
BSF PORTA,2 ;RSを1にセット
BSF PORTA,0 ;E high ストローブ信号出力
BCF PORTA,0 ;E low
SWAPF DPDT,W ;get data lower
ANDLW 0F0H ;下位4ビットの転送
MOVWF PORTB
BSF PORTA,0 ;ストローブ信号出力
BCF PORTA,0
CALL LCD_BUSY ;Busy信号が無くなるまで待つ
RETURN
;**** LCD Busy Check ****
LCD_BUSY
CLRF DPDT ;データバッファクリア
BSF STATUS,RP0 ;PICモード変更のためBank1へ切替え
BSF OPTION_REG,7 ;ポートBのプルアップをOFF指定
MOVLW 0FEH ;PORTBRB0以外を入力モードにセット
MOVWF TRISB
BCF STATUS,RP0 ;Bank 0へ戻す
BCF PORTA,2 ;RSを0にセット
BSF PORTA,1 ;R/Wを1にセット Busy入力モードをセット
BSF PORTA,0 ;E high ストローブ信号出力
MOVF PORTB,W ;データを2回に分けて入力
BCF PORTA,0 ;E low
ANDLW 0F0H ;まず上位4ビットを入力
MOVWF DPDT ;一時保存
BSF PORTA,0 ;E high 次のストローブ信号出力
MOVF PORTB,W ;下位4ビットを入力
BCF PORTA,0 ;E low
ANDLW 0FH ;Mask out upper
IORWF DPDT,F ;上位と下位をORで合併
BTFSC DPDT,7 ;BUSY FLAGビットをチェック
GOTO LCD_BUSY ;Busy状態だったら再度入力繰り返し
;
BCF PORTA,1 ;R/Wを0に戻す(出力モードに戻す)
BSF STATUS,RP0 ;PICのモード変更のためBank 1へ切替え
MOVLW 0EH ;RB1,2,3 以外は出力へ戻す
MOVWF TRISB ;PORTBモードセット
BCF STATUS,RP0 ;Bank 0へ戻す
RETURN
;**** LCD Initialize ****
LCD_INI
CALL TIME5M ;15msec以上待つ(5msec3回待ちにしている)
CALL TIME5M
CALL TIME5M
MOVLW 030H ;8ビットモード設定制御
MOVWF PORTB
BCF PORTA,1 ;R/W 0セット
BCF PORTA,2 ;RS 0セット
BSF PORTA,0 ;E high ストローブ
BCF PORTA,0 ;E low
CALL TIME5M ;4.1msec以上待つ(5msec待ち)
MOVLW 030H ;再度8ビットモード設定制御
MOVWF PORTB
BCF PORTA,1 ;R/W 0セット
BCF PORTA,2 ;RS 0セット
BSF PORTA,0 ;E high ストローブ
BCF PORTA,0 ;E low
CALL TIME02M ;100usec以上待つ(200usec待ち)
MOVLW 030H ;再々度8ビットモード設定制御
MOVWF PORTB
BCF PORTA,1 ;R/W 0セット
BCF PORTA,2 ;RS 0セット
BSF PORTA,0 ;ストローブ
BCF PORTA,0
CALL TIME02M ;念のため200usec待ち
MOVLW 020H ;4ビットモード設定制御
MOVWF PORTB ;(この時はまだ8ビットモード)
BCF PORTA,1 ;R/W 0セット
BCF PORTA,2 ;RS 0セット
BSF PORTA,0 ;ストローブ
BCF PORTA,0
CALL TIME02M ;念のため200usec待ち
;以降4ビットモードで動作かつBusyFlag有効
MOVLW 02CH ;Function Set(101100 4ビット、2行、5x10Dot表示指定)
CALL LCD_CMD
MOVLW 08H ;Display off (1000 表示オフ、Cursor,Blinkなし)
CALL LCD_CMD
MOVLW 0CH ;Display on (1100 表示オン、Cursor,Blinkなし)
CALL LCD_CMD
MOVLW 06H ;Entry Mode Set(Incrementオン,表示シフト指定なし)
CALL LCD_CMD
RETURN
;*****表示クリア*****
LCD_CLR MOVLW 01H ;表示クリア(1)
CALL LCD_CMD
CALL TIME1S
RETURN
;
;タイマーサブルーチン10MHzオシレータの場合
;10MHzの場合周期は0.1usec、実行サイクルは0.4usec
;
;0.2msecサブルーチン 500サイクル*0.4usec
TIME02M MOVLW 07CH ;1 124回まわす
MOVWF CNT1 ;1 2
TIMLP1 NOP ;1
DECFSZ CNT1,F ;1
GOTO TIMLP1 ;2 2+4*124-1=497
NOP ;1 498
RETURN ;2 500 500*0.4usec=0.2msec
;5msec 12500サイクル
TIME5M MOVLW 019H ;1 25回まわす
MOVWF CNT2 ;1
TIMLP2 CALL TIME02M ;2+500=502
DECFSZ CNT2,F ;1
GOTO TIMLP2 ;2 2+505*25-1=12626
RETURN ;2 12628 5.05msec
;50msec 125000
TIME50M MOVLW 0F8H ;248回
MOVWF CNT3 ;ここまでで2サイクル
TIMLP3 CALL TIME02M ;2+500
DECFSZ CNT3,F ;1
GOTO TIMLP3 ;2 2+505*248-1=125241
RETURN ;2 125243 50.1msec
;1sec
TIME1S MOVLW 014H ;20回
MOVWF CNT4 ;50msec * 20
TIMLP4 CALL TIME50M
DECFSZ CNT4,F ;このループは50msec
GOTO TIMLP4
RETURN
END

これで一応アセンブルエラーは出なかったけど、シミュレーションデバッグは例によってやっていない

だってタイマーサブルーチンでぐるぐるループしててVirtualPCではなかなか進まないんだもの。