第16週 
;16F877でステッピングモータとLCD同時操作
;*********************************************
        LIST        P=PIC16F877   ;
        INCLUDE     "P16f877.inc" ;標準ヘッダ定義ファイル
        __CONFIG    _HS_OSC & _PWRTE_ON & _WDT_OFF & _LVP_OFF 
 
;*********************************************
CNT     EQU     020H            ;出力パターン用カウンタ
WTEMP   EQU     021H            ;Wレジスタ待避
STTEMP  EQU     022H            ;STATUSレジスタ待避
INTTMCT EQU     023H            ;割り込みタイマ設定値
TIMCNT  EQU     024H            ;タイマ用カウンタ
TIM5CNT EQU     025H
TIM1CNT EQU     026H
LCDDT   EQU     027H            ;LCD表示データ格納
LCDINST EQU     028H            ;LCDインストラクション格納

;***********************
;  メインルーチン
;***********************
        ORG     0               ;Reset Start
        GOTO    MAIN
        ORG     04H             ;Int
        GOTO    INTR
        
MAIN                            ;Initialize        
        BSF     STATUS,RP0      ;バンク1へ切替
        BCF     INTCON,GIE      ;割り込み禁止
        MOVLW   07H
        MOVWF   ADCON1          ;A/D用ピンを全てデジタルI/Oに
        MOVLW   07H             ;
        MOVWF   OPTION_REG      ;内部クロック、プリスケーラ1:256
        MOVLW   01H
        MOVWF   TRISA           ;とりあえずポートAをRA0入力、他は出力モード設定
        CLRF    TRISB           ;とりあえずポートBを出力モードに設定
        CLRF    TRISC           ;とりあえずポートCを出力モードに設定
        CLRF    TRISD           ;とりあえずポートDを出力モードに設定
        CLRF    TRISE           ;とりあえずポートEを出力モードに設定
        BCF     STATUS,RP0      ;バンク0に戻す
        
        MOVLW   B'10010000'     ;初期出力
        MOVWF   PORTD
        MOVLW   0H              ;COUNTER初期出力
        MOVWF   CNT
        
        MOVLW   03CH            ;タイマ値ロード
        MOVWF   TMR0            ;約500Hz
        MOVWF   INTTMCT         ;タイマ値記憶
        BSF     INTCON,T0IE     ;TMR0オーバーフロー割り込み発生許可
        BSF     INTCON,GIE      ;割り込み許可


;LCD初期化
        CALL    TIM5            ;まず15msec以上待ち
        CALL    TIM5
        CALL    TIM5
        CALL    TIM5 
        MOVLW   030H
        MOVWF   PORTB
        BCF     PORTE,1         ;R/WをWに
        BCF     PORTE,2         ;RSをインストラクションに
        BSF     PORTE,0         ;E
        NOP
        BCF     PORTE,0

        CALL    TIM5            ;4.1msec以上待ち
        MOVLW   030H
        MOVWF   PORTB
        BCF     PORTE,1         ;R/WをWに
        BCF     PORTE,2         ;RSをインストラクションに
        BSF     PORTE,0         ;E
        NOP
        BCF     PORTE,0

        CALL    TIM02           ;100μsec以上待ち
        CALL    TIM02
        MOVLW   030H
        MOVWF   PORTB
        BCF     PORTE,1         ;R/WをWに
        BCF     PORTE,2         ;RSをインストラクションに
        BSF     PORTE,0         ;E
        NOP
        BCF     PORTE,0

        CALL    TIM02
        CALL    TIM02
        MOVLW   038H            ;Function Set 8ビット 2行 5×7ドット
        CALL    LCDCMD
        MOVLW   01H             ;表示クリア
        CALL    LCDCMD        
        MOVLW   06H             ;エントリーモード                
        CALL    LCDCMD
        MOVLW   0CH             ;表示ON
        CALL    LCDCMD
        
;文字書き込み(いくらなんでもちょっと能なしすぎるプログラム(^^; )
;MotorとRun を交互に表示
CHW
        CALL    LCDCLR          ;表示クリア
        CALL    TOMBO
        CALL    LCD2L           ;2行目へ
        CALL    KIMURA
        CALL    TIM1S
CHW2    CALL    LCDCLR
        CALL    KIMURA
        CALL    LCD2L
        CALL    TOMBO           
        CALL    TIM1S
        GOTO    CHW
 
;***********************
;サブルーチン
;***********************
TOMBO                           ;表示Motor
        MOVLW   'M'
        CALL    LCDDTW
        MOVLW   'o'
        CALL    LCDDTW
        MOVLW   't'
        CALL    LCDDTW
        MOVLW   'o'
        CALL    LCDDTW
        MOVLW   'r'
        CALL    LCDDTW

        RETURN
KIMURA
        MOVLW   'R'            ;表示Run
        CALL    LCDDTW
        MOVLW   'u'
        CALL    LCDDTW
        MOVLW   'n'
        CALL    LCDDTW

        RETURN
        


LCDDTW                          ;LCDデータ書き込み
                                ;Wに書き込まれたデータ(1文字)を表示
        MOVWF   PORTB
        BCF     PORTE,1         ;R/WをW
        BSF     PORTE,2         ;RSをデータに
        BSF     PORTE,0         ;E
        NOP
        BCF     PORTE,0
        CALL    LCDBUSY         ;BUSYチェック
        RETURN

LCDCMD                          ;LCDインストラクション書き込み
                                ;Wレジスタに書き込まれたコマンドをLCDへ
        MOVWF   PORTB
        BCF     PORTE,1         ;R/WをW
        BCF     PORTE,2         ;RSをインストラクションに
        BSF     PORTE,0         ;E
        NOP
        BCF     PORTE,0
        CALL    LCDBUSY         ;BUSYチェック
        RETURN

LCDCLR                          ;LCD表示クリア
        MOVLW   01H
        CALL    LCDCMD
        RETURN
LCD2L                           ;2行目へ
;◎データシートによると1行目と2行目はアドレスが連続していないで
;2行目の第1文字目は40(H)番地らしい
;(b'1*******'が表示アドレス書き込み  *******を1000000として2行目先頭指令)
        MOVLW   0C0H
        CALL    LCDCMD
        RETURN

LCDBUSY                         ;LCD BUSYチェック
                                ;やっかいなことにいちいちPORTBを入力に変えて
                                ;さらにOPTIONレジスタで弱プルアップに設定
        BSF     STATUS,RP0      ;バンク1へ切替
        MOVLW   0FFH            ;ポートBを入力モードに設定
        MOVWF   TRISB
        BCF     STATUS,RP0      ;バンク0に戻す
        BCF     PORTE,2         ;RSをインストラクションに
        BSF     PORTE,1         ;R/WをR
        BSF     PORTE,0         ;E
        NOP
        BCF     PORTE,0
        MOVF    PORTB,W
        MOVWF   LCDINST
        BTFSC   LCDINST,7       ;BUSYフラグチェック
        GOTO    LCDBUSY

        BCF     PORTE,1         ;R/WをWに戻しておく
        BSF     STATUS,RP0      ;バンク1へ切替
        CLRF    TRISB           ;ポートBを出力モードに設定
        BCF     STATUS,RP0      ;バンク0に戻す
        RETURN


TIM02                           ;約0.2mSECタイマ
        MOVLW   0FFH
        MOVWF   TIMCNT
TIMLP   NOP
        DECFSZ  TIMCNT,F
        GOTO    TIMLP
        RETURN
TIM5                            ;約5msecタイマ
        MOVLW   01AH
        MOVWF   TIM5CNT
TIM5LP  CALL    TIM02
        DECFSZ  TIM5CNT,F
        GOTO    TIM5LP
        RETURN
TIM1S                          ;約1secタイマ
        MOVLW   0C8H
        MOVWF   TIM1CNT
TIM1SLP CALL    TIM5
        DECFSZ  TIM1CNT,F
        GOTO    TIM1SLP
        RETURN

;*********************************************************
;割り込み処理
INTR
        BCF     INTCON,T0IF     ;割り込みフラグクリア 
        MOVWF   WTEMP           ;レジスタ待避
        
        SWAPF   STATUS,W
        MOVWF   STTEMP
        
        BCF     STATUS,RP0      ;バンク0に戻す
        ;◎メインプログラム中でバンク切り替えをし、かつ割り込みの中で
        ; STATUSをチェックするので互いに影響を及ぼさないようにここで
        ; バンク0にしておく
        ;(復帰についてはレジスタ復帰するので考慮不要)
        MOVF    INTTMCT,W       ;タイマ値ロード
        SUBLW   0F5H            ;◎タイマ値FB(5KHz)まではINCしていく
        BTFSS   STATUS,Z        ; タイマ値と比較して同じならスキップ
        INCF    INTTMCT,F       ; 違うなら(大きいなら)INC
        MOVF    INTTMCT,W
        MOVWF   TMR0            ;
        
FWD                             ;正転カウント処理
        MOVF    CNT,W
        SUBLW   07H
        BTFSC   STATUS,2
        GOTO    SET0            ;カウンタ値 7 なら 0 に
        INCF    CNT,F
        GOTO    INCED
SET0    MOVLW   0H
        MOVWF   CNT
INCED   

PATTERN
        MOVF    CNT,W
        CALL    TABLE
        MOVWF   PORTD

        SWAPF   STTEMP,W        ;レジスタ復帰
        MOVWF   STATUS
        SWAPF   WTEMP,F
        SWAPF   WTEMP,W

        RETFIE

TABLE
        ADDWF   PCL,F
        RETLW   B'10010000'
        RETLW   B'00010000'
        RETLW   B'00110000'
        RETLW   B'00100000'
        RETLW   B'01100000'
        RETLW   B'01000000'
        RETLW   B'11000000'
        RETLW   B'10000000'

;*********************************************************

        END