;**************************************************************************** ;  リモート操作装置のPIC_16F84ソフト   特製Linux本体装置専用  2005/10/01 ; ; RS232C経由 双方向シリアル通信 9600bps, non_parity, 8bits_data, 1stop_bit ; Timer0 interrupt採用、RTS&CTS不使用 http://www.picfun.com/equipj30.htmlより引用 ; ; 受信データの20文字4行LCD表示、ボタンのほかロータリエンコーダ状態の送信   ; ; If you use this modules, you must check RECV flag for waiting ; received data in main routine. ; ; The status register "RESULT"'s bits are explained below. ; BIT0 : TXBUSY (1 is tarnsimission in progress) ; BIT1 : unused ; BIT2 : RXBUSY (1 indicates in receive process) ; BIT3 : RECV (1 indicates there are received data) ; BIT4 : ERROR (1 indicates any error) ; The flag of "BUSY" is send/receive busy flag,check before use. ; ; ; PORTA RA0,2 LCD 制御出力 0:E 2:RS(R/Wはロー固定、書き込み専用に) ; RA1 LED点灯表示出力 ; RA3 : シリアル送信出力 ; RA4 : シリアル受信入力 ; PORTB RB0-3 LCD_DATA出力(常時)/ボタン入力(必要時だけ切り替える) ; RB4-7 ロータリエンコーダ入力(ビット7,6使用 5,4−将来拡張用) ; ;  REリードではチャタリング対処  ステイタス送信は 20h〜7FhのASCII文字コード範囲内に ; チャタ除去処理付でミリ秒サイクルで常時監視し積算データを保持  ; その時点での積算値を 20h〜7FhというASCII文字コード範囲内の ; 96のコードの循環データ値での応答としました ; (RE使用のLinux側応用テストプログラムでの実績の結果 この形にした ; 1.16進データでは循環量不足だった  ; 2.生のバイトデータでは 制御コードで問題発生  ということでした) ; ; ;                     MPASMにてアセンブルのこと ;***************************************************************** ; LIST P=PIC16F84 INCLUDE "P16F84.INC" __CONFIG _HS_OSC & _PWRTE_ON & _WDT_OFF ;======================================================== ;************************************* ; Define constant module ;************************************* #DEFINE TXBUSY RESULT,0 ;sending #DEFINE RXBUSY RESULT,2 ;receiving #DEFINE RECV RESULT,3 ;receive end #DEFINE ERROR RESULT,4 ;error bit ;**** Define Variables ***** RESULT EQU 0CH ;current status WREG EQU 0DH ;wreg save area SREG EQU 0EH ;status reg save area BITCNT EQU 0FH ;send bit counter EXTRA EQU 10H ;stop bit flag TXREG EQU 11H ;send data buffer RXREG EQU 12H ;receive data buffer RXREG_1 EQU 13H ;追加バッファ CNT2_I EQU 14H ;Timer counter for 10us for INTRPTprocess CNT2 EQU 15H ;Timer counter for 10us ;***** for LCD variables **** DPDT EQU 16H ;buffer for display data CNT1 EQU 17H ;Timer counter for 100us CNT3 EQU 18H ;Timer counter for 1ms CNT4 EQU 19H ;Timer counter for 5ms POS EQU 0x20 POS_SAVE EQU 0x21 ;**** ROTARY ENCODER *********** ROTARY EQU 0x22 ;読み取り値(前後)バッファ ROTARY_DATA EQU 0x23 ;累算結果 TEMP EQU 0x24 ;チャタ対策用temp CNT_re EQU 0x25 ;チャタ対策用ms_Delay_Counter ;**** EEPROM DATA ;取りあえずです <-PENDING E_ADRS EQU 0x26 E_DATA EQU 0x27 ORG 02100H DE 02AH, 01H, 03FH, 0 DE "Hello!", 0 ;************************************* ; Jump vector ;************************************* ORG 0 ;reset GOTO START ORG 4 ;Interrupt GOTO INTERRUPT ORG 08H ;code ;******************************************************** ; rotary encoder data read ;     REリードではチャタリング対処  ステイタス送信は 20h〜7FhのASCII文字コード範囲内に ;******************************************************** ROTARY_READ_P0 MOVF PORTB,W ; ANDLW B'11000000' ; Bit 7,6 XORWF TEMP,F ;ここでのZフラグ MOVWF TEMP ;movwfはzフラグに影響与えない BTFSS STATUS,Z ;ここで使用 TEMPと同じ? RETURN ;初回の変化 チャタ対策で戻す TEMPにはホールド ;(ミリ秒近くのwaitを期待) MOVF TEMP,W ;ここで 2度読み変化無し持続のBit 7,6を採用 IORWF ROTARY,F ; SWAPF ROTARY,W ;Bit 7-4に保持されている ANDLW B'00001111' ; Bit 7,6 ADDWF PCL,F ; L_ROTARY GOTO NORMAL ; 0000 GOTO NORMAL ; 0001 UP GOTO NORMAL ; 0010 DOWN GOTO NORMAL ; 0011 GOTO NORMAL ; 0100 DOWN GOTO NORMAL ; 0101 GOTO NORMAL ; 0110 GOTO NORMAL ; 0111 UP GOTO NORMAL ; 1000 UP GOTO NORMAL ; 1001 GOTO NORMAL ; 1010 GOTO NORMAL ; 1011 DOWN GOTO NORMAL ; 1100 GOTO DOWN ; 1101 GOTO UP ; 1110 L_ROTARY_END GOTO NORMAL ; 1111 L_ROTARY_B ; IF (HIGH(L_ROTARY)!=HIGH(L_ROTARY_B-1)) ; ERROR "L_ROTARYテーブルエラー" ; ENDIF ; ; ; ;-------------------------------- ; rotary encoder up mode - 7FH ;-------------------------------- UP MOVLW 1 ; ADDWF ROTARY_DATA,F ; MOVF ROTARY_DATA,W ; <- データを 持って来て 80H以上か吟味 SUBLW 7FH ;kk-wreg -> wreg 結果 0,posのとき Cが1です 注意!! BTFSC STATUS,C ;80h以上だと(C立たず)スキップですね  GOTO ROTARY_READ_P0_OK ; MOVLW 20H MOVWF ROTARY_DATA ;ROTARY_DATAを20Hに更新 GOTO ROTARY_READ_P0_OK ; ; ;-------------------------------- ; rotary encoder down mode 20H - ;-------------------------------- DOWN MOVLW -1 ; ADDWF ROTARY_DATA,F ; MOVF ROTARY_DATA,W ; <- データを 持って来て 1FH以下か吟味 SUBLW 1FH ;kk-wreg -> wreg 結果 0,posのとき Cが1です 注意!! BTFSS STATUS,C ;1FH以下だと(C立ち)スキップですね  GOTO ROTARY_READ_P0_OK ; MOVLW 7FH MOVWF ROTARY_DATA ;ROTARY_DATAを7FHに更新 GOTO ROTARY_READ_P0_OK ; ; ;-------------------------------- ; rotary encoder not moveing ;-------------------------------- NORMAL NOP ; ; ROTARY_READ_P0_OK RRF ROTARY,F ; -> RRF ROTARY,F ; -> MOVLW B'00110000' ; ANDWF ROTARY,F ; RETURN ; ;******************************************************** ; binary to ascii routine 下位4BITのHex変換 ;******************************************************** BIN_2_ASC ANDLW 0x0F ; ADDWF PCL,F ; BIN_2_ASC_TBL RETLW '0' ; RETLW '1' ; RETLW '2' ; RETLW '3' ; RETLW '4' ; RETLW '5' ; RETLW '6' ; RETLW '7' ; RETLW '8' ; RETLW '9' ; RETLW 'A' ; RETLW 'B' ; RETLW 'C' ; RETLW 'D' ; RETLW 'E' ; BIN_2_ASC_END RETLW 'F' ; BIN_2_ASC_T_B ; IF (HIGH(BIN_2_ASC_TBL)!=HIGH(BIN_2_ASC_T_B-1)) ; ERROR "BIN_2_ASC_TBLテーブルエラー" ; ENDIF ; ; ; ;******************************************************** CONTROL_CODE MOVF RXREG_1,W ;get received data ;このあと制御文字分岐処理 <- ADDWF PCL,F ; JUMP_TABLE GOTO DISP_clr ;0x0 ^@ ヌル 画面クリア、カーソルホーム GOTO POS_1 ;0x1 ^a LCD1行目頭へ POS保存 ;引き続きの\オクタルデータ指定あればその位置へ ;無ければ行頭(ただし次は必ず文字であること) 位置データは文字とは重ならない GOTO POS_2 ;0x2 ^b LCD2行目頭へ POS保存  GOTO POS_3 ;0x3 ^c LCD3行目頭へ POS保存 GOTO POS_4 ;0x4 ^d LCD4行目頭へ POS保存 GOTO POS_RSTR ;0x5 ^e POSコール以前の位置に戻す GOTO DISP_TEST ;6 ^f GOTO DISP_TEST ;7 ^g ベル GOTO DISP_BS ;8 BS,\b ^h バックスペース(行頭判断し行替え処理もします) GOTO DISP_ht ;9 HT,\t ^i タブ GOTO DISP_CR ;A LF,\n ^j \rと同じ処理に(行頭では改行せず) GOTO DISP_TEST ;B VT,\v ^k GOTO POS_1 ;とりあえず ;C FF,\f ^l カーソル位置設定 GOTO DISP_CR ;0x0D CR,\r ^m 改行・行末まで空白埋め ;行頭では(4行と限られたエリアなので)改行せず SP+改行で一行空白になる GOTO DISP_TEST ;E SO ^n GOTO DISP_TEST ;F SI ^o eepromから64バイト読み取り GOTO LED_ON ;10 ^p LED on GOTO LED_OFF ;11 ^q LED off GOTO DISP_TESTr ;12 ^r ロータリエンコーダの操作状況データの応答をします ; チャタ除去処理付でミリ秒サイクルで常時監視し積算データを保持  ; その時点での積算値を 20h〜7FhというASCII文字コード範囲内の ; 96のコードの循環データ値での応答としました ; (RE使用のLinux側応用テストプログラムでの実績の結果 この形にした ; 1.16進データでは循環量不足だった  ; 2.生のバイトデータでは 制御コードで問題発生  ということでした) ; GOTO DISP_TESTs ;13 ^s ボタンSW読み取り用 4つのボタンが下位4ビットに対応していて ; 40hを加算し文字化した応答です 4つのボタン全てopenで "O"(4Fh) ; 押された位置がlowの文字G,K,M,Nなどです ; 連続押しで困る場合は 一度開放されるのを待つ処理などで、  ; 同時押し判定は時間差を配慮し数回のコールなどして対処のこと  ;   GOTO DISP_TEST ;14 ^t GOTO DISP_TEST ;15 ^u GOTO DISP_TEST ;16 ^v GOTO DISP_TEST ;17 ^w GOTO DISP_TEST ;18 ^x GOTO DISP_TEST ;19 ^y GOTO DISP_TEST ;1A ^z GOTO DISP_TEST ;1B ^[ GOTO CMD2LCD ;0x1C ^\ LCDへの直接制御 (使用には注意が必要です) ; 引き続きの受信データまでも必要とする特別なコードです ; Linux本体側のプログラムで LCDモジュールの機能を制御、 ; 例えば ^\^aで表示クリア、^\^b or ^cでカーソルホーム ; ^\^lでブリンクオフ、^\^mでブリンクオン など行えます ; CGRAMアドレス設定のあとフォントパターンデータのセット ; し 自作のキャラクタも出せます しかし 0x20〜3fなどは ; LCDの動作モードの設定といった機能設定ですので 問題を ; 起こします また 使用後は初期設定に戻すことが肝要です ; LCDモジュールの仕様書を詳しく調べながら使用するように GOTO DISP_TEST ;1D ^] GOTO DISP_TEST ;1E ^^ GOTO DISP_TEST ;1F ^_ ;******************************************************** ; Fill Blank_CHR routine CR時の行末までの空白埋め ;******************************************************** FILL_BLANK SUBLW 0x00 ;行頭でzero、一文字目が-1、n文字目が-nで ;callされますので kk -W -> W を利用し符号反転 ADDWF PCL,F ; CALL CHR_FILL ;20個sp埋め 0では跳んでこないが 一般化 CALL CHR_FILL ;19  CALL CHR_FILL ;18 CALL CHR_FILL ;17 CALL CHR_FILL ;16 CALL CHR_FILL ;15 CALL CHR_FILL ;14 CALL CHR_FILL ;13 CALL CHR_FILL ;12 CALL CHR_FILL ;11 CALL CHR_FILL ;10 CALL CHR_FILL ;9 CALL CHR_FILL ;8 CALL CHR_FILL ;7 CALL CHR_FILL ;6 CALL CHR_FILL ;5 CALL CHR_FILL ;4 CALL CHR_FILL ;3 CALL CHR_FILL ;2 CALL CHR_FILL ;1 RETURN ;0 CHR_FILL MOVLW " " ;SPACE CALL LCD_DATA INCF POS,F RETURN ;************************************* ; Initialise process ;************************************* START BCF INTCON,T0IE ;TMR0 interrupt disable BCF INTCON,GIE ;Interrupt disable CLRF RESULT ;Reset status CALL PORT_INI ;Initialise CALL LCD_INI ;Reset LCD MOVLW 20H MOVWF ROTARY_DATA ;ROTARY_DATAを20Hに ;************************************* ; Main loop for waiting any event ;************************************* MAIN CALL LCD_CLR ;clear display ;初期化チェック済み表示 MOVLW "O" CALL LCD_DATA ;display O MOVLW "K" CALL LCD_DATA ;display K MOVLW " " CALL LCD_DATA ;display SPACE ;初期化チェック済み表示<-ここまで MOVLW 0x80 ;POSの初期化 MOVWF POS CALL LCD_CMD ; BSF INTCON,GIE ;permit interrupt ;**** ボタンチェックと 受信データ有無 の チェックループ EVENT CALL GETCHAR ;受信許可 (受信完でRECVflag->0、RXREG_1にデータ) RCVWAIT CALL ROTARY_READ_P0 ;RE チャタ対策で2度読み式 ;ms近くの間隔で コールする MOVLW 0xFF ; チャタ対策用ms_細かくし回数増し MOVWF CNT_re ; Delay_Counterカウンタ廻し T_LP_re BTFSS RECV ;受信データ の 有無チェックしながら GOTO RECVed ;(受信したときはwait時間変わる いいね?) NOP NOP NOP NOP DECFSZ CNT_re,F ;2+8*255-1=2000 (*0.4=0.8ms) GOTO T_LP_re ;のRE読み出しのループ GOTO RCVWAIT ;**** LOOP抜けた    RECVed BTFSC ERROR ;error check GOTO ERR MOVF RXREG_1,W ; <- 追加バッファからにしました SUBLW 01FH ;kk-wreg -> wreg 結果 0,posのとき Cが1です 注意!! BTFSC STATUS,C ;SPや文字だと(C立たず)スキップですね  GOTO CONTROL_CODE ;0x00〜0x1f を制御コード扱いで ; 分析(計算ジャンプ)テーブルへ MOVF RXREG_1,W ;文字ですね <- 追加バッファからにしました CALL SR_W2LCD ;文字なら すぐLCD表示しましょう  ;20文字超えると自動改行してくれます GOTO EVENT ;そして 次の受信待ちループへ戻る ;******* 0x1C ^\ LCDへの直接制御 (使用には注意が必要です) ; 引き続きの受信データまでも必要とする特別なコードです CMD2LCD CALL GETCHAR ;受信許可 (受信完でRECVflag->0、RXREG_1にデータ) RCVWAIT_CMD ;待ちの間 どうする? 特別なので何もしない BTFSC RECV ; GOTO RCVWAIT_CMD ; BTFSC ERROR ;error check GOTO ERR MOVF RXREG_1,W ; CALL LCD_CMD ;引き続きの受信データをLCDへCMDとして渡します GOTO EVENT ;******* 文字表示・位置データ更新  自動改行 のSRです  Wに文字コードをsetしてあること SR_W2LCD CALL LCD_DATA ;文字は LCD表示へ INCF POS,F ;文字位置データ カウントアップ MOVF POS,W ;文字位置データの分析、処理 SUBLW 0x94 ;   BTFSC STATUS,Z GOTO SR_POS_2 ;1行目超えた 改行必要 MOVF POS,W ;文字位置データ SUBLW 0xD4 ;   BTFSC STATUS,Z GOTO SR_POS_3 ;2行目超えた MOVF POS,W ;文字位置データ SUBLW 0xA8 ;改行必要? の条件処理   BTFSC STATUS,Z GOTO SR_POS_4 ;3行目超えた MOVF POS,W ;文字位置データ SUBLW 0xE8 ;改行必要? の条件処理   BTFSC STATUS,Z GOTO SR_POS_1 ;4行目超えた RETURN ;超えなかった ;******* 文字位置データ更新SR & 行末まで空白文字埋め・改行SR ; SR_FILL_BLANKへは Wに行末までの文字数をsetしてあること ; 行頭でzero、一文字目が-1、n文字目が-nでcallします SR_FILL_POS_2 CALL FILL_BLANK SR_POS_2 MOVLW 0C0H ;2行目頭へ 40h GOTO SR_POS_CHG SR_FILL_POS_3 CALL FILL_BLANK SR_POS_3 MOVLW 094H ;3行目頭へ 14h GOTO SR_POS_CHG SR_FILL_POS_4 CALL FILL_BLANK SR_POS_4 MOVLW 0D4H ;4行目頭へ 54h GOTO SR_POS_CHG SR_FILL_POS_1 CALL FILL_BLANK SR_POS_1 MOVLW 080H ;1行目頭へ 00h SR_POS_CHG MOVWF POS ;POSを更新 CALL LCD_CMD ;LCDへもCMD渡し RETURN ;******* 位置データ変更  コントロールコードでの利用 POS_1 MOVF POS,W ;cont+a MOVWF POS_SAVE ; MOVLW 080H ;1行目頭へ 00h GOTO POS_move POS_2 MOVF POS,W ;cont+b MOVWF POS_SAVE ; MOVLW 0C0H ;2行目頭へ 40h GOTO POS_move POS_3 MOVF POS,W ;cont+c MOVWF POS_SAVE ; MOVLW 094H ;3行目頭へ 14h GOTO POS_move POS_4 MOVF POS,W ;cont+d MOVWF POS_SAVE ; MOVLW 0D4H ;4行目頭へ 54h POS_move MOVWF POS CALL GETCHAR ;引き続きのデータ受信許可 RCVWAIT_POS ;待ちの間 どうする? 特別なので何もしない BTFSC RECV ; GOTO RCVWAIT_POS ; BTFSC ERROR ;error check GOTO ERR MOVF RXREG_1,W ; SUBLW 01FH ;kk-wreg -> wreg 結果 0,posのとき Cが1です 注意!! BTFSC STATUS,C ;SPや文字だと(C立たず)スキップですね  GOTO POS_move2 ;0x00〜0x1f を位置データ扱いで POSに加算 MOVF POS,W ;文字ですね <- 文字位置 行頭のままで セットし  CALL LCD_CMD ; MOVF RXREG_1,W ;文字として 表示へ CALL SR_W2LCD ; GOTO EVENT ;そして 次の受信待ちへ POS_move2 MOVF RXREG_1,W ;0x00〜0x13(\23) 位置データ 0x14以上はどうする? SUBLW 013H ;kk-wreg -> wreg 結果 0,posのとき Cが1です 注意!! BTFSS STATUS,C ;0x00〜0x13(\23)だと(C立ち)スキップですね  GOTO POS_move3 ;0x14〜 では POSに加算せず MOVF RXREG_1,W ADDWF POS,F ;位置データ扱いで POSに加算 POS_move3 MOVF POS,W ;文字位置セット  CALL LCD_CMD GOTO EVENT ;そして 次の受信待ちへ POS_RSTR MOVF POS_SAVE,W ;cont+e MOVWF POS ;文字位置戻し  CALL LCD_CMD GOTO EVENT ; ;******* 改行コードの処理です  行末まで空白埋め・改行です  cont+m or "Enter" ;       処理時間掛かるので GETCHARコールしてます 戻しは RCVWAITになります DISP_CR ; CALL GETCHAR ;時間の掛かるCR処理の前に 次の受信準備 MOVF POS,W ;文字位置データ SUBLW 0xD4 ; kk-wreg -> wreg 結果 0,posのとき Cが1です 注意!!  BTFSC STATUS,Z GOTO RCVWAIT ;そのまま 戻り 行頭でのCR無効にしました BTFSS STATUS,C GOTO FILL_POS_1 ;1行目へ D4を超えていた 4行目だったので MOVF POS,W ;文字位置データ SUBLW 0xC0 ;   BTFSC STATUS,Z GOTO RCVWAIT ;そのまま 戻り 行頭でのCR無効にしました BTFSS STATUS,C GOTO FILL_POS_3 ;3行目 MOVF POS,W ;文字位置データ SUBLW 0x94 ;   BTFSC STATUS,Z GOTO RCVWAIT ;そのまま 戻り 行頭でのCR無効にしました BTFSS STATUS,C ;kk-wreg -> wreg 結果 0,posのとき Cが1です 注意!! GOTO FILL_POS_4 ;4行目 改行 MOVF POS,W ;文字位置データ SUBLW 0x80 ;   BTFSC STATUS,Z GOTO RCVWAIT ;そのまま 戻り 行頭でのCR無効にしました BTFSS STATUS,C ;kk-wreg -> wreg 結果 0,posのとき Cが1です 注意!! GOTO FILL_POS_2 ;2行目 改行 GOTO RCVWAIT ;ここへは来ること無いはずだが FILL_POS_1 CALL SR_FILL_POS_1 GOTO RCVWAIT ;そして 戻りは RCVWAITです FILL_POS_2 CALL SR_FILL_POS_2 GOTO RCVWAIT ;そして 戻りは RCVWAITです FILL_POS_3 CALL SR_FILL_POS_3 GOTO RCVWAIT ;そして 戻りは RCVWAITです FILL_POS_4 CALL SR_FILL_POS_4 GOTO RCVWAIT ;そして 戻りは RCVWAITです ;******* DISP_BS DECF POS,F ;文字位置データ カウントdown MOVF POS,W ;文字位置データの分析、処理 SUBLW 0x7F ;   BTFSC STATUS,Z GOTO POS_4end ;1行目頭を外れた POS再計算必要 MOVF POS,W ;文字位置データ SUBLW 0xBF ;   BTFSC STATUS,Z GOTO POS_1end ;2行目頭を外れた POS再計算必要 MOVF POS,W ;文字位置データ SUBLW 0x93 ;条件処理   BTFSC STATUS,Z GOTO POS_2end ;3行目頭を外れた POS再計算必要 MOVF POS,W ;文字位置データ SUBLW 0xD3 ;条件処理   BTFSC STATUS,Z GOTO POS_3end ;4行目頭を外れた POS再計算必要 BS_WR MOVF POS,W ; CALL LCD_CMD MOVLW " " CALL LCD_DATA ;SPACEを記入 MOVF POS,W ;も一度POS設定し直し CALL LCD_CMD GOTO EVENT POS_1end MOVLW 093H ;1行目末へ GOTO POS_CHGend POS_2end MOVLW 0D3H ;2行目末へ GOTO POS_CHGend POS_3end MOVLW 0A7H ;3行目末へ GOTO POS_CHGend POS_4end MOVLW 0E7H ;4行目末へ POS_CHGend MOVWF POS ; GOTO BS_WR ;******* DISP_ht MOVLW 0A5H ;ht文字"*" 表示へ CALL SR_W2LCD ;POSもカウントアップ GOTO EVENT ;そして 次の受信待ちへ ;******* LED LED_ON BSF PORTA,1 ;LED on cont+p GOTO EVENT LED_OFF BCF PORTA,1 ;LED off cont+q GOTO EVENT ;******* DISP_clr CALL LCD_CLR ; GOTO EVENT ;******* cont+s REデータ送出 DISP_TESTr MOVF ROTARY_DATA,W ; CALL BIN_2_ASC ;下位4bitのHex変換 9-29 生データ送出に MOVWF TXREG CALL PUTCHAR GOTO WAITLP_tx ;*******  ノーアクションです DISP_TEST ;no action GOTO EVENT ;******* cont+s ボタンチェックとデータ送出 DISP_TESTs BSF STATUS,RP0 ;Set page 1 MOVLW 0FFH ;<--RB3-0も入力に for ボタンチェック MOVWF TRISB ;PortB set all output BCF STATUS,RP0 ;Set Page 0 この設定 読み取ったあと もどせよ CALL TIME10 MOVF PORTB,W ;RB読み取り keyINバッファに ANDLW B'00001111' ADDLW 040H ;文字化 MOVWF TXREG BSF STATUS,RP0 ;Set page 1 MOVLW 0F0H ;ボタンチェック終了で RB3-0を出力に戻す  MOVWF TRISB ; BCF STATUS,RP0 ;Set Page 0 CALL PUTCHAR WAITLP_tx BTFSC TXBUSY ;wait end of sending GOTO WAITLP_tx CALL TIME10 GOTO EVENT ;*** receive error display **** ERR MOVLW "?" CALL SR_W2LCD ;表示そして EVENT戻り GOTO EVENT ;****************************************************************** ;************** RS232C PROCESS ********************************** ;**** Preset Baud Rate **** ;************ Define constant for TIMER0 **** ; BaudRate PulseWidth Counter prescale TMR0(BITTMR) width ; 300 3333.33usec 8333 64(5) 130(7E) 3328usec ; 1200 833.33 2083 16(3) 130(7E) 832 ; 2400 416.67 1041 8(2) 128(80) 409 ; 4800 208.33 521 4(1) 124(84) 198 ; 9600 104.17 260 2(0) 122(86) 99 ; This TMR0 RATE is used for BAUDRATE parameter as prescaler. ; ;BAUDRATE:boud rate 300 to 9600 at 10MHz clock. ; 5=300bps 3=1200bps 2=2400bps 1=4800bps 0=9600bps ; BAUDRATE SET 0 ;preset to 9600bps BITTMR SET 086H ;TMR0 DATA -122 BITTMR1 SET 06AH ;TMR0 DATA -150 ; ;**************************************** ; Interrupt process module ;**************************************** INTERRUPT BTFSS INTCON,T0IF ;TMR0's interrupt? RETFIE ;not, quick return BCF INTCON,T0IF ;reset T0IF bit ;**** save W register & status register MOVWF WREG ;save w reg SWAPF STATUS,W ;status to wreg MOVWF SREG ;save status BTFSC TXBUSY ;In send mode GOTO TXNEXT ;send next bit BTFSC RXBUSY ;In receive mode GOTO RXNEXT ;receive next bit GOTO STARTBIT ;must be start bit ;**** register restore and return RESTORE SWAPF SREG,W ;get saved status MOVWF STATUS SWAPF WREG,F ;get saved wreg SWAPF WREG,W RETFIE ;************************************ ; Transmission process module ;************************************ PUTCHAR BSF TXBUSY ;set busy bit MOVLW 8 ;bit count MOVWF BITCNT ;reset bit counter MOVLW 1 MOVWF EXTRA ;set stopbit flag CALL TXSTART ;start send dumy bit BCF INTCON,T0IF ;reset flag BSF INTCON,T0IE ;permit TMR0 interrupt RETFIE ;**** Send start bit **** TXSTART CLRF TMR0 ;reset timer BSF STATUS,RP0 ;page 1 CLRWDT MOVLW BAUDRATE ;set prescaler MOVWF OPTION_REG BCF STATUS,RP0 ;page 0 BCF PORTA,3 ;send start bit MOVLW BITTMR MOVWF TMR0 ;start timer RETURN ;****** Interrupt process for Send next bit ***** TXNEXT MOVLW BITTMR ;timer restart MOVWF TMR0 MOVF BITCNT,1 ;end test BTFSC STATUS,Z GOTO STOPBIT ;send stop bit NEXTTXBIT DECF BITCNT,F ;BITCNT-1 BSF STATUS,C ;C on RRF TXREG,1 ;shift send data BTFSS STATUS,C ;bit test BCF PORTA,3 ;0 out BTFSC STATUS,C BSF PORTA,3 ;1 out GOTO RESTORE ;return ;**** Send Stop bit **** STOPBIT MOVF EXTRA,W BTFSC STATUS,Z ;end test GOTO DONE ;goto end DECF EXTRA,F ;end of stop BSF PORTA,3 ;send 1 for stop bit GOTO RESTORE ;return ;*** all end of send **** DONE BCF INTCON,T0IE ;Disable interrupt BCF TXBUSY ;reset busy flag GOTO RESTORE ;return ;************************************************************** ;************************************* ; Receiving process module ;************************************* GETCHAR BSF RECV ;wait bit on MOVLW 9 MOVWF BITCNT ;set bit counter CLRF RXREG ;clear buffer BCF ERROR ;clear error bit ;**** Start bit wait **** CLRF TMR0 ;timer reset BSF STATUS,RP0 ;page 1 CLRWDT ;clear WDT MOVLW 038H ;set to external WDT MOVWF OPTION_REG BCF STATUS,RP0 ;page 0 MOVLW 0FFH MOVWF TMR0 ;set timer for start bit BCF INTCON,T0IF BSF INTCON,T0IE ;enable TMR0 interrupt RETFIE ;wait interrupt ;**** Start bit process **** STARTBIT CLRWDT ;timer reset CALL TIME10_I ;Delay 10usec BTFSC PORTA,4 ;retry GOTO NOISE ;not start bit BSF RXBUSY ;set busy ; CLRF TMR0 ;reset timer for next bit BSF STATUS,RP0 ;page 1 MOVLW BAUDRATE ; MOVWF OPTION_REG BCF STATUS,RP0 ;page 0 MOVLW BITTMR1 ;set bit width over 1.1bit MOVWF TMR0 GOTO RESTORE ;return ;*** missing start bit **** NOISE MOVLW 0FFH ;retry MOVWF TMR0 GOTO RESTORE ;return ;**** receive next bit **** RXNEXT BSF STATUS,RP0 ;page 1 CLRWDT ;reset timer MOVLW BAUDRATE MOVWF OPTION_REG BCF STATUS,RP0 ;page 0 MOVLW BITTMR MOVWF TMR0 ;restart timer DECFSZ BITCNT,F ;counter-1 GOTO NEXTRXBIT ;*** stop bit process *** BTFSS PORTA,4 ;stop bit check BSF ERROR ;not stop BCF INTCON,T0IE ;inhibit interrupt BCF RXBUSY ;reset busy flag BCF RECV ;set receive complete ; ;**** If pararell process, insert call at this position **** ; CALL RECEIVEPROCESS MOVF RXREG,W ;追加バッファにコピーを置いて MOVWF RXREG_1 ;REREGを早く開放、LCD処理待たずに 次の受信を許可 GOTO RESTORE ;**** next bit process *** NEXTRXBIT BCF STATUS,C ;prepare bit for shift BTFSC PORTA,4 ;data=0 or 1? BSF STATUS,C ;1 case RRF RXREG,F ;set data to RXREG GOTO RESTORE ;***** 10usec delay routine for INTRPTprocess TIME10_I ;10usec for INTRPTprocess MOVLW 7H MOVWF CNT2_I T_LP2_I DECFSZ CNT2_I,F ;2+3*7-1=22 GOTO T_LP2_I RETURN ;22+1=23 ;****************** This is the end of RS232C modules ********************* ;****************************************************** ; PORT A & B Initialize Routine ; This routine includes RS232C and LCD initilization. ;****************************************************** PORT_INI BSF STATUS,RP0 ;Set page 1 MOVLW 0F0H ;RB4,5,6,7 RE入力 RB0-3はLCDへ出力 ;RB0-3については ボタン読み取りでは入力(0FFH) MOVWF TRISB ;PortB BCF OPTION_REG,7 ;zeroで RB in PullUp使用するです MOVLW 010H ;only RA4 input MOVWF TRISA ;PortA set BCF STATUS,RP0 ;Set Page 0 BSF PORTA,3 ;RS232 TX SET TO H BSF PORTA,1 ;LED TO H on 初期 点灯 どっちがいい? RETURN ;*************************************************************************** ;*************************************************** ; LCD control routines ;*************************************************** ;**** LCD Data Write **** LCD_DATA MOVWF DPDT ;save dat SWAPF DPDT,W ;<- RB3-0がDB7-4に接続されてるので ANDLW 0FH ;mask lower <- 0F0ではなく0Fで MOVWF PORTB BSF PORTA,2 ;RS high BSF PORTA,0 ;E high BCF PORTA,0 ;E low MOVF DPDT,W ;get data lower ANDLW 0FH ;mask lower <- 0F0ではなく0Fで MOVWF PORTB BSF PORTA,0 BCF PORTA,0 CALL TIME10 CALL TIME10 CALL TIME10 CALL TIME10 ;40us以上の固定 フラグ監視を止めました RETURN ;**** LCD command out ***** LCD_CMD MOVWF DPDT ;save dat SWAPF DPDT,W ;<- RB3-0がDB7-4に接続されてるので ANDLW 0FH ;mask lower <- 0F0ではなく0Fで MOVWF PORTB BCF PORTA,2 ;RS low BSF PORTA,0 ;E high BCF PORTA,0 ;E low MOVF DPDT,W ;get data lower ANDLW 0FH ;mask lower <- 0F0ではなく0Fで MOVWF PORTB BSF PORTA,0 BCF PORTA,0 CALL TIME10 CALL TIME10 CALL TIME10 CALL TIME10 ;40us以上の固定 フラグ監視を止めました ;表示クリアとカーソルホームでは 1.6ms以上ということで  ;そちらで 2ms位の待ちを入れて下さい RETURN ;**** LCD Display Clear **** LCD_CLR MOVLW 01H ;clear command CALL LCD_CMD MOVLW 0x80 ;Position 0,0 <-80H このままLCD_CMDに渡せます MOVWF POS CALL TIME1M ;<- 固定ディレイに :1.6ms以上 CALL TIME1M RETURN ;**** Initialize ***** LCD_INI CALL TIME5M ;wait CALL TIME5M ;wait CALL TIME5M ;wait CALL TIME5M ;wait MOVLW 03H ;Function set 8bits <-030 MOVWF PORTB BCF PORTA,2 ;RS BSF PORTA,0 ;E high BCF PORTA,0 ;E low CALL TIME5M ;wait MOVLW 03H ;Function reset 8bits <-030 MOVWF PORTB BCF PORTA,2 ;RS BSF PORTA,0 ;E high BCF PORTA,0 ;E low CALL TIME100 MOVLW 03H ;Function reset 8bits <-030 MOVWF PORTB BCF PORTA,2 BSF PORTA,0 BCF PORTA,0 CALL TIME100 MOVLW 02H ;Function set 4bits mode <-020 MOVWF PORTB ;under the 8bits mode BCF PORTA,2 BSF PORTA,0 BCF PORTA,0 CALL TIME100 ;From here 4bits mode MOVLW 028H ;function DL=0 4bit mode,5x7:40us CALL LCD_CMD MOVLW 08H ;Display off D=C=B=0 :40us CALL LCD_CMD MOVLW 0CH ;Display on D=1 C=B=0 :40us CALL LCD_CMD MOVLW 06H ;Entry I/D=1 S=0 :40us CALL LCD_CMD RETURN ;********************************* ; Timer Routine ; TIME10 :10usec ; TIME100 :100usec ; TIME1M :1msec ; TIME5M :5msec ;********************************* ;***** 10usec delay routine TIME10 ;10usec  MOVLW 7H MOVWF CNT2 T_LP2 DECFSZ CNT2,F ;2+3*7-1=22 GOTO T_LP2 RETURN ;22+1=23 TIME100 ;100usec MOVLW 9H MOVWF CNT1 T_LP1 CALL TIME10 ;2+(25+3)*9-1=253 DECFSZ CNT1,F GOTO T_LP1 RETURN ;254*0.4=100usec(about) TIME1M ;1msec(about) MOVLW 0AH MOVWF CNT3 T_LP3 CALL TIME100 ;2+(254+3)*10-1=2541 DECFSZ CNT3,F GOTO T_LP3 RETURN ;2542 TIME5M ;5msec(about) MOVLW 3BH MOVWF CNT4 T_LP4 CALL TIME100 ;2+(254+3)*59-1=15164 DECFSZ CNT4,F GOTO T_LP4 RETURN ;15165 ;*************************************************************************** ;*************************************************** ; EEPROM routines 10:27 2005/08/24現在 動作未確認ですよ!! ; E_ADRS : データエリアのアドレス   E_DATA : データ  E_ADRSとE_DATAは変数 ;*************************************************** RD_EEPROM MOVF E_ADRS,W ;データエリアのアドレス指定 MOVWF EEADR ;Set address register BSF STATUS,RP0 ;Set to page 1 BSF EECON1,RD ;Start read BCF STATUS,RP0 ;Return to page 0 MOVF EEDATA,W ;Wレジスタにデータ取り出し RETURN WR_EEPROM BCF STATUS,RP0 ;Set to page 0 MOVF E_ADRS,W ;データエリアのアドレス指定 MOVWF EEADR ;Address set MOVF E_DATA,W ;書き込むデータ MOVWF EEDATA ;Data set BSF STATUS,RP0 ;Set to Page 1 BSF EECON1,WREN ;Set WR Enable MOVLW 55H ;Write Sequence MOVWF EECON2 ;Start write MOVLW 0AAH MOVWF EECON2 BSF EECON1,WR ;Go write WR_LP ;書き込み確認待ちループ BTFSC EECON1,WR ;Check Write end GOTO WR_LP BCF STATUS,RP0 ;Return to page 0 RETURN END