;ソフトウェアTXルーチンは、 ;ELECTRONICS SHELVES ;http://www4.zero.ad.jp/electronics/index.htmlから入手しました(実際には以前のアドレスから)。 ;入手先で著作権の掲示はありませんでした。~ ; ;I2C関係ルーチンはMicrochipのAppNotesから入手しました。 ;個人使用用途でのみ使用が許されています。 ;本ソースファイルの上記個所以外の著作権は ;disklessfun(disklessfun@mail.goo.ne.jp) ;に帰属します。 ;BSDライセンスとします。 ;どうぞ、割とご自由にお使い下さい。 ; 2006/7/29 ; 2007/3/10に上の入手先を修正 ;*********************************************************** ; ; 232Cデータロガー兼リピーター ソースファイル ; ;*********************************************************** LIST P=16F877A include "p16f877a.inc" ; Include file for a PIC16F877A __CONFIG _HS_OSC & _PWRTE_ON & _WDT_OFF & _LVP_OFF errorlevel -302 ; Suppress message 302 from list file ;----------------------------------------------------------- ; EEPROM データ org 0x21FE de 0x00,0x00 ;*********************************************************** ; 変数定義とレジスタ割付 ;*********************************************************** CBLOCK H'20' W_SAVE STATUS_SAVE PCLATH_SAVE r_flg ; RS-232C受信フラグ btn_state ; PORTTのBit4,5 btn_state_bk ; 15mS前の値 btn_state_acpt ; 前回変化した際の値 FLGBUTTON ; (<0>flg_dual, <1>flg_red, <2>flg_grn) FLGCOLLECT ; (<0>flg_sp, <1>flg_sp2, <2>flg_done, <3>flg_full) ; flg_sp 3秒計測中フラグ ; flg_sp2 3秒経過後フラグ ; flg_done ; flg_full EEPROM満杯 flg_sleep ; FF=カウント可能状態、0、カウント不可状態、1=sleep可能状態 blnkcnt ; 点滅処理用カウンタ FLGBLNK ; <0>flg_blnk 点滅処理用フラグ tm0mulcnt tm0spcnt ; アドレスセーブ用カウント(受信フラグ兼用、FFhでOFFの意味) tmr0slpcnt_h ; sleepカウントH tmr0slpcnt_l ; sleepカウントL data_ee_addr data_ee_data ; --- I2C work address_h address_l address_h_save address_l_save address_h_prnt address_l_prnt dataw ; Writable Data datasave ; datai ; Data input byte buffer datao ; Data output byte buffer bytecount ; Counter for byte loops pollcnt ; Counter for polling loops loops ; Delay loop counter loops2 ; Delay loop counter ; --- Sort Serial send work txd rs ; ビットタイムの作業用 cn ; 8ビットシフトの作業用 wk1 ; work wk2 ; work ; --- Wait routin work tim0 tim1 tim2 ENDC WRITE_ADDR equ b'10100000' ; Control byte for write operations READ_ADDR equ b'10100001' ; Control byte for read operations ; for development ;;ADRH_MAX equ h'01' ;ADRH_MAX equ b'00000001' ; 64K bit ;;ADRH_MAX equ h'1F' ;ADRH_MAX equ b'00011111' ; 256K bit ;;ADRH_MAX equ h'7F' ADRH_MAX equ b'01111111' TMR0INIT equ d'110' TMR0MUL1S equ d'64' TMR0MUL3S equ d'191' TMR0_3M_H equ d'47' ;TMR0_3M_H equ d'2' BTIME equ 53h ; 9600bps 10MHz 時のウエイトタイム SAV_EEADDR_H equ h'FF' SAV_EEADDR_L equ h'FE' BTNMASK equ b'00110000' BTNINIVAL equ b'00110000' BTNDUALSTATE equ b'00000000' BTNREDSTATE equ b'00100000' BTNGRNSTATE equ b'00010000' #define PORTSOFTTX PORTA,0 #define PORTRTS PORTA,1 #define PORTRED PORTB,1 #define PORTGRN PORTB,2 #define PORTPWR PORTB,7 #define BTNRED btn_state,4 #define BTNGRN btn_state,5 #define flg_dual FLGBUTTON,0 #define flg_red FLGBUTTON,1 #define flg_grn FLGBUTTON,2 #define flg_sp FLGCOLLECT,0 #define flg_sp2 FLGCOLLECT,1 #define flg_done FLGCOLLECT,2 #define flg_full FLGCOLLECT,3 #define flg_blnk FLGBLNK,0 org 0 goto START org H'4' ;*********************************************************** ; 割り込みルーチン ;*********************************************************** INT_START bsf PORTRTS ; RS-232C受信禁止 movwf W_SAVE ; Copy W to TEMP register swapf STATUS,W ; Swap status to be saved into W clrf STATUS ; bank 0, regardless of current bank, Clears IRP,RP1,RP0 movwf STATUS_SAVE ; Save status to bank zero STATUS_SAVE register movf PCLATH,W ; Only required if using pages 1, 2 and/or 3 movwf PCLATH_SAVE ; Save PCLATH into W clrf PCLATH ; Page zero, regardless of current page bcf INTCON,GIE ; グローバル割り込みをOFF ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INT_DISC btfsc INTCON,RBIF ; RBIFか否かを判定 btfss INTCON,RBIE ; RBIEが有効かを判定 goto $+2 goto INT_RB btfsc INTCON,TMR0IF ; TMR0IFか否かを判定 goto INT_TMR0 btfsc PIR1,TMR2IF ; TMR2IFか否かを判定 goto INT_TMR2 goto INT_END ; 不要(デバッグ用) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INT_RB bcf INTCON,RBIF ; フラグクリア bsf PORTGRN call WAITL bcf PORTGRN goto INT_END ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INT_TMR0 bcf INTCON,TMR0IF ; フラグクリア movlw TMR0INIT ; 通常、 movwf TMR0 ; 15mS毎に割り込みが入るようにする incf blnkcnt,F movlw b'00000011' andwf blnkcnt,W btfsc STATUS,Z incf FLGBLNK,F ; タイマ割り込み4回毎にON、OFF ; このブロックはflg_sleepが0=カウント不可状態の場合のみ処理 movf flg_sleep,F btfss STATUS,Z goto $+6 btfsc PORTPWR ; PORTPWRがLowの場合、 goto $+4 movlw h'FF' movwf flg_sleep ; flg_sleepをカウント可能状態=FFに call INIT_SLPTMR ; sleepタイマー初期化 ; このブロックはflg_sleepがFF=カウント可能状態の場合のみ処理 incfsz flg_sleep,W goto $+10 btfss PORTPWR ; PORTPWRがHighの場合、 goto $+3 clrf flg_sleep ; flg_sleepをカウント不可状態=0に goto $+6 incfsz tm0spcnt,W ; tm0spcntの状態で分岐 goto $+3 call DEC_SLPCNT ; tm0spcnt未使用=FFhの場合、sleepタイマーデクリメント goto $+2 call INIT_SLPTMR ; tm0spcnt使用中の場合、sleepタイマー初期化 nop nop nop nop nop nop nop incfsz tm0spcnt,W ; tm0spcnt使用中の場合、 call INC_SACNT btfsc flg_dual ; flg_dualが立っている場合、 call INC_DUALCNT btfsc flg_red ; flg_redが立っている場合、 call INC_REDCNT btfsc flg_grn ; flg_grnが立っている場合、 call INC_GRNCNT btfsc flg_sp ; flg_spが立っている場合、 call INC_SPCNT call BTN_CHK btfsc STATUS,C goto INT_TMR0_END ; 変化していない場合は無視 call BTN_ACCPT call BTN_DUALCHK btfss STATUS,C goto INT_TMR0_MID_END ; この処理をおこなった場合は後の処理はしない call BTN_REDCHK btfss STATUS,C goto INT_TMR0_MID_END ; この処理をおこなった場合は後の処理はしない call BTN_GRNCHK btfss STATUS,C goto INT_TMR0_MID_END ; この処理をおこなった場合は後の処理はしない call BTN_DUALREL call BTN_REDREL call BTN_GRNREL INT_TMR0_MID_END movf btn_state,W movwf btn_state_acpt INT_TMR0_END movf btn_state,W movwf btn_state_bk goto INT_END ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INT_TMR2 bcf PIR1,TMR2IF ; フラグクリア goto INT_END ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INT_END bsf INTCON,GIE ; グローバル割り込みをON movf PCLATH_SAVE,W ; Restore PCLATH movwf PCLATH ; Move W into PCLATH swapf STATUS_SAVE,W ; Swap STATUS_SAVE register into W ;(sets bank to original state) movwf STATUS ; Move W into STATUS register swapf W_SAVE,F ; Swap W_SAVE swapf W_SAVE,W ; Swap W_SAVE into W bcf PORTRTS ; RS-232C受信許可 RETFIE ;--------------------------------------------------------------------- INIT_SLPTMR movlw TMR0_3M_H ; 3分間分の値をセット movwf tmr0slpcnt_h clrf tmr0slpcnt_l return ;--------------------------------------------------------------------- DEC_SLPCNT decf tmr0slpcnt_l,F btfsc STATUS,Z decf tmr0slpcnt_h,F movf tmr0slpcnt_h,F btfss STATUS,Z return movlw h'01' movwf flg_sleep ; sleep可能状態 return ;--------------------------------------------------------------------- INC_SACNT incf tm0spcnt,F movf tm0spcnt,W sublw TMR0MUL1S btfss STATUS,C ; 入力後1秒以内の場合、点滅処理 goto INC_SACNT_1 btfsc flg_full goto INC_SACNT_BLNK_RED INC_SACNT_BLNK_GRN ; 満杯ではない場合、 movf FLGBUTTON,F ; 緑を点滅 btfss STATUS,Z ; ただし、押下状態の場合は除外 goto INC_SACNT_1 btfsc flg_blnk goto $+3 bsf PORTGRN goto $+2 bcf PORTGRN goto INC_SACNT_1 INC_SACNT_BLNK_RED ; 満杯の場合、 movf FLGBUTTON,F ; 赤を点滅 btfss STATUS,Z ; ただし、押下状態の場合は除外 goto INC_SACNT_1 btfsc flg_blnk goto $+3 bsf PORTRED goto $+2 bcf PORTRED goto INC_SACNT_1 INC_SACNT_1 movlw TMR0MUL3S subwf tm0spcnt,W btfss STATUS,Z return movlw h'FF' movwf tm0spcnt ; フラグOFF bcf PORTGRN bcf PORTRED btfss flg_full ; 満杯フラグが立っていない場合、 call SAVE_EE_SAVPNT ; セーブポイント保存 return ;--------------------------------------------------------------------- INC_DUALCNT btfsc flg_done ; 処理済みフラグが立っていれば中止 return incf tm0mulcnt,F ; 倍数カウントをインクリメント movlw TMR0MUL3S subwf tm0mulcnt,W btfss STATUS,Z return bsf flg_done ; 処理済みフラグを立てる bcf flg_sp2 ; flg_sp2を落とす call CLR_ALL ; 全消去 return ;--------------------------------------------------------------------- INC_REDCNT btfsc flg_done ; 処理済みフラグが立っていれば中止 return incf tm0mulcnt,F ; 倍数カウントをインクリメント movlw TMR0MUL1S subwf tm0mulcnt,W btfss STATUS,Z return bsf flg_done ; 処理済みフラグを立てる btfss flg_sp2 ; flg_sp2が立っていれば、SET_PRNTPNT else PRINT_ALL goto $+3 call SET_PRNTPNT ; 出力開始ポイント設定 return call PRINT_ALL ; 順方向に出力 return ;--------------------------------------------------------------------- INC_GRNCNT btfsc flg_done ; 処理済みフラグが立っていれば中止 return incf tm0mulcnt,F ; 倍数カウントをインクリメント movlw TMR0MUL1S subwf tm0mulcnt,W btfss STATUS,Z return bsf flg_done ; 処理済みフラグを立てる btfss flg_sp2 ; flg_sp2が立っていれば、ERS_PRNTPNT else PRINT_ALL goto $+3 call ERS_PRNTPNT ; 出力開始ポイント消去 return call PRINT_ALL ; 逆方向に出力 return ;--------------------------------------------------------------------- INC_SPCNT incf tm0mulcnt,F ; 倍数カウントをインクリメント movlw TMR0MUL3S subwf tm0mulcnt,W btfss STATUS,Z return bcf flg_sp ; flg_spを落とす return ;--------------------------------------------------------------------- BTN_CHK movf PORTB,W andlw BTNMASK movwf btn_state subwf btn_state_bk,W btfss STATUS,Z ; 2回続けて同じ値か確認する goto BTN_CHK_END movf btn_state,W subwf btn_state_acpt,W btfsc STATUS,Z ; 前回採用値と同じ場合は無視 goto BTN_CHK_END bcf STATUS,C return BTN_CHK_END bsf STATUS,C return ;--------------------------------------------------------------------- BTN_ACCPT movf btn_state,W movwf wk1 comf wk1,F rrf wk1,F rrf wk1,F rrf wk1,F movlw b'00000110' andwf wk1,F movf PORTB,W andlw b'11111001' iorwf wk1,W movwf PORTB ; btfss BTNGRN ; 上記セクションと結果は同じ ; goto $+3 ; bcf PORTGRN ; goto $+2 ; bsf PORTGRN ; ; btfss BTNRED ; goto $+3 ; bcf PORTRED ; goto $+2 ; bsf PORTRED return ;--------------------------------------------------------------------- BTN_DUALCHK btfsc flg_dual ; flg_dualが立っていれば中止 goto BTN_DUALCHK_END movf btn_state,W sublw BTNDUALSTATE btfss STATUS,Z ; 両ボタンとも押されている場合、 goto BTN_DUALCHK_END bsf flg_dual ; flg_dualを立てる bcf flg_red ; flg_redを落とす bcf flg_grn ; flg_grnを落とす bcf flg_sp ; flg_spを落とす clrf tm0mulcnt ; 倍数カウントを初期化 bcf flg_done ; 処理済みフラグを初期化 bcf STATUS,C return BTN_DUALCHK_END bsf STATUS,C return ;--------------------------------------------------------------------- BTN_REDCHK movf btn_state_acpt,W sublw BTNINIVAL btfss STATUS,Z ; 前回、何も押されていなくて、 goto BTN_REDCHK_END movf btn_state,W sublw BTNREDSTATE btfss STATUS,Z ; 今回、Rボタンだけが押されいる場合、 goto BTN_REDCHK_END bsf flg_red ; flg_redを立てる btfss flg_sp ; flg_spが立っていた場合、 goto $+3 bcf flg_sp ; flg_spを落として、 bsf flg_sp2 ; flg_sp2を立てる clrf tm0mulcnt ; 倍数カウントを初期化 bcf flg_done ; 処理済みフラグを初期化 bcf STATUS,C return BTN_REDCHK_END bsf STATUS,C return ;--------------------------------------------------------------------- BTN_GRNCHK movf btn_state_acpt,W sublw BTNINIVAL btfss STATUS,Z ; 前回、何も押されていなくて、 goto BTN_GRNCHK_END movf btn_state,W sublw BTNGRNSTATE btfss STATUS,Z ; 今回、Gボタンだけが押されている場合、 goto BTN_GRNCHK_END bsf flg_grn ; flg_grnを立てる btfss flg_sp ; flg_spが立っていた場合、 goto $+3 bcf flg_sp ; flg_spを落として、 bsf flg_sp2 ; flg_sp2を立てる clrf tm0mulcnt ; 倍数カウントを初期化 bcf flg_done ; 処理済みフラグを初期化 bcf STATUS,C return BTN_GRNCHK_END bsf STATUS,C return ;--------------------------------------------------------------------- BTN_DUALREL btfss flg_dual ; flg_dualが立っていなければ中止 goto BTN_DUALREL_END movf btn_state,W sublw BTNDUALSTATE btfsc STATUS,Z ; 両ボタンとも押されているわけではない場合、 goto BTN_DUALREL_END bcf flg_dual ; flg_dualを落とす bsf flg_sp ; flg_spを立てる clrf tm0mulcnt ; 倍数カウントを初期化 bcf flg_done ; 処理済みフラグを初期化 return BTN_DUALREL_END return ;--------------------------------------------------------------------- BTN_REDREL btfss flg_red ; flg_redが立っていなければ中止 goto BTN_REDREL_END movf btn_state,W sublw BTNREDSTATE btfsc STATUS,Z ; Rボタンだけが押されているわけではない場合、 goto BTN_REDREL_END bcf flg_red ; flg_redを落とす bcf flg_sp2 ; flg_sp2を落とす return BTN_REDREL_END return ;--------------------------------------------------------------------- BTN_GRNREL btfss flg_grn ; flg_grnが立っていなければ中止 goto BTN_GRNREL_END movf btn_state,W sublw BTNGRNSTATE btfsc STATUS,Z ; Gボタンだけが押されているわけではない場合、 goto BTN_GRNREL_END bcf flg_grn ; flg_grnを落とす bcf flg_sp2 ; flg_sp2を落とす return BTN_GRNREL_END return START ;*********************************************************** ; 入出力ピン初期化 ;*********************************************************** bsf STATUS,RP0 ; Bank 1 へ切替 ; movlw B'00000110' ; 全Port ディジタル入出力に設定 movlw B'00000111' ; 全Port ディジタル入出力に設定 movwf ADCON1 ; ADCON1レジスタの設定 movlw b'11111100' ; RA0はSoft Serial、RA1はRTS movwf TRISA movlw b'11111001' ; movwf TRISB movlw b'11111111' movwf TRISC ; Set PORTC to all inputs movlw b'11111111' movwf TRISD movlw b'11111111' movwf TRISE ; bcf OPTION_REG,7 ; PORTB pull-up ; bcf OPTION_REG,T0CS ; internal ; bcf OPTION_REG,PSA ; Timer0 module ; bsf OPTION_REG,2 ; <2:0>=111 = Timer0,1:256prescale ; bsf OPTION_REG,1 ; ; bsf OPTION_REG,0 ; movlw b'01010111' movwf OPTION_REG bsf PIE1,TMR2IE ; Timer2 enable movlw B'00100100' ; 8ビット、送信イネーブル、非同期、高速ボーレート選択 movwf TXSTA ; movlw 040H ; SPBRG=64(9600) movlw B'01000000' ; SPBRG=64(9600) movwf SPBRG bcf STATUS,RP0 ; Bank 0 へ切替 ; movlw 090H ; シリアルピン、8ビット、連続受信 movlw B'10010000' ; シリアルピン、8ビット、連続受信 movwf RCSTA call InitI2C ; Initialize device ; bsf T2CON,6 ; <6:3>=1111 = Timer2,1:16postscale ; bsf T2CON,5 ; ; bsf T2CON,4 ; ; bsf T2CON,3 ; ; bcf T2CON,2 ; Timer2 is off ; bsf T2CON,1 ; <1:0>=10 = Timer2,1:16prescale ; bsf T2CON,0 ; movlw b'01111011' movwf T2CON movlw TMR0INIT movwf TMR0 clrf TMR2 bcf INTCON,RBIF bcf INTCON,TMR0IF bcf PIR1,TMR2IF ; bsf INTCON,PEIE ; peripheral interrupt enable ; bsf INTCON,RBIE ; PORTB change interuppt enable ※注意:この行をコメントアウトしてもRBIFは発生する bsf INTCON,TMR0IE ; Timer0 enable ; bsf T2CON,TMR2ON ; Timer2 enable ;*********************************************************** ; その他初期化 ;*********************************************************** bsf PORTSOFTTX bcf PORTRTS clrf PORTB movlw BTNINIVAL movwf btn_state_bk movwf btn_state_acpt clrf FLGBUTTON clrf FLGCOLLECT clrf flg_sleep movlw h'FF' movwf tm0spcnt ; フラグOFFの意味 bsf PORTGRN call WAITL bcf PORTGRN call READ_EE_SAVPNT ; セーブポイント読み出し ; グローバル割り込みスタート bsf INTCON,GIE ; interrupt enable ;*********************************************************** ; ループ ;*********************************************************** MAIN_LOOP bcf INTCON,GIE call REPT bsf INTCON,GIE movlw d'30' movwf wk2 nop decfsz wk2,F goto $-2 decfsz flg_sleep,W ; flg_sleepがsleep可能状態=1の場合、 goto $+9 clrf flg_sleep ; flg_sleep初期化 bcf PORTGRN bsf PORTRED call WAITL bcf PORTRED bcf INTCON,RBIF bsf INTCON,RBIE ; PORTB change interuppt enable ※注意:この行をコメントアウトしてもRBIFは発生する sleep nop btfsc INTCON,RBIE ; RBIEが有効かを判定 bcf INTCON,RBIE ; PORTB change interuppt disable bcf PORTRTS ; RS-232C受信許可 goto MAIN_LOOP ;----------------------------------------------------------- ; サブルーチン ;----------------------------------------------------------- ;*********************************************************** ; セーブポイント保存 ;************************************************************ SAVE_EE_SAVPNT movlw SAV_EEADDR_H movwf data_ee_addr movf address_h,W movwf data_ee_data call WRITE_EEPROM movlw SAV_EEADDR_L movwf data_ee_addr movf address_l,W movwf data_ee_data call WRITE_EEPROM return ;*********************************************************** ; セーブポイント読み出し ;************************************************************ READ_EE_SAVPNT movlw SAV_EEADDR_H movwf data_ee_addr call READ_EEPROM movwf address_h ; 入力開始アドレスHigh movwf address_h_prnt ; 出力開始アドレスHigh movlw SAV_EEADDR_L movwf data_ee_addr call READ_EEPROM movwf address_l ; 出力開始アドレスLow movwf address_l_prnt ; 出力開始アドレスLow movf address_h,W ; address_hが sublw ADRH_MAX ; ADRH_MAXで、 btfss STATUS,Z ; goto READ_EE_SAVPNT_END incfsz address_l,W ; address_lがFFhの場合、 btfss STATUS,Z ; goto READ_EE_SAVPNT_END bsf flg_full ; 満杯フラグを立てる goto READ_EE_SAVPNT_END movf address_h,W ; address_hが sublw ADRH_MAX ; ADRH_MAXを btfsc STATUS,C ; 超えていた場合は満杯フラグを立てる goto READ_EE_SAVPNT_END bsf flg_full ; 満杯フラグを立てる READ_EE_SAVPNT_END return ;*********************************************************** ; 全消去処理 ;************************************************************ CLR_ALL clrf address_h clrf address_l CLR_ALL_1 call SET_FLG_BLNK btfsc flg_blnk goto $+3 bsf PORTRED bcf PORTGRN btfss flg_blnk goto $+3 bcf PORTRED bsf PORTGRN clrw call ByteWrite ; Byte Write operation incf address_l,F btfsc STATUS,Z incf address_h,F ;; movf address_h,W ; address_hが sublw ADRH_MAX ; ADRH_MAXを btfsc STATUS,C ; 超えるまで goto CLR_ALL_1 clrf address_h clrf address_l clrf address_h_prnt clrf address_l_prnt bcf flg_full ; 満杯フラグを落とす return ;*********************************************************** ; 全出力処理 ;************************************************************ PRINT_ALL movf address_l,W movwf address_l_save movf address_h,W movwf address_h_save movf address_l_prnt,W movwf address_l movf address_h_prnt,W movwf address_h PRINT_ALL_1 call SET_FLG_BLNK btfsc flg_blnk goto $+5 btfsc flg_red bsf PORTRED btfsc flg_grn bsf PORTGRN btfss flg_blnk goto $+5 btfsc flg_red bcf PORTRED btfsc flg_grn bcf PORTGRN call ByteRead ; Byte Read operation btfsc STATUS,Z ; NULL値の場合はそれ以降の読み出しを中止 goto PRINT_ALL_2 btfsc flg_red call SEND btfsc flg_grn call SoftTx incf address_l,F btfsc STATUS,Z incf address_h,F ;; movf address_h,W ; address_hが sublw ADRH_MAX ; ADRH_MAXを btfsc STATUS,C ; 超えていなければ、 goto PRINT_ALL_1 ; goto PRINT_ALL_2 movf address_l_save,W movwf address_l movf address_h_save,W movwf address_h return ;*********************************************************** ; 点滅用処理 ;************************************************************ SET_FLG_BLNK incf blnkcnt,F movlw b'00011111' andwf blnkcnt,W btfsc STATUS,Z incf FLGBLNK,F ; 32回呼び出される毎にON、OFF return ;*********************************************************** ; 出力開始ポイントを設定 ;************************************************************ SET_PRNTPNT movf address_h,W movwf address_h_prnt movf address_l,W movwf address_l_prnt bsf PORTGRN call WAITL bcf PORTGRN return ;*********************************************************** ; 出力開始ポイントを消去 ;************************************************************ ERS_PRNTPNT clrf address_h_prnt clrf address_l_prnt bsf PORTRED call WAITL bcf PORTRED return ;*********************************************************** ; RS-232リピート処理 ;************************************************************ REPT clrf r_flg call RCV btfss r_flg,0 return bsf PORTRTS ; RS-232C受信禁止 clrf tm0spcnt ; セーブポイント保存用タイマーリセット call SEND btfsc flg_full ; 満杯フラグが立っていると中止 goto REPT_END call ByteWrite ; Byte Write operation movf address_h,W ; address_hが sublw ADRH_MAX ; ADRH_MAXで、 btfss STATUS,Z ; goto REPT_MID_END incfsz address_l,W ; address_lがFFhの場合、 btfss STATUS,Z ; goto REPT_MID_END bsf flg_full ; 満杯フラグを立てる bcf PORTGRN call SAVE_EE_SAVPNT ; セーブポイント保存 clrf address_h_prnt clrf address_l_prnt goto REPT_END REPT_MID_END incf address_l,F btfsc STATUS,Z incf address_h,F REPT_END return ;*********************************************************** ; RS-232C一文字受信 ;************************************************************ RCV BTFSS PIR1,RCIF GOTO RCV_NODATA MOVF RCREG,W BTFSC RCSTA,FERR GOTO RCV_ERROR BTFSC RCSTA,OERR GOTO RCV_ERROR BSF r_flg,0 RETURN RCV_NODATA RETURN RCV_ERROR BSF RCSTA,ADDEN BCF RCSTA,ADDEN RETURN ;*********************************************************** ; シリアル一文字送信サブルーチン ;*********************************************************** SEND bsf STATUS,RP0 ; BANK1 LPSEND btfss TXSTA,TRMT ; TSR空チェック goto LPSEND bcf STATUS,RP0 ; BANK0 movwf TXREG return SEND2 BTFSS PIR1,TXIF goto SEND2 movwf TXREG return ;*********************************************************** ; WAITサブルーチン ;*********************************************************** WAITL ; 約440mS movlw H'1D' movwf tim0 goto WA0 WAITS ; 約15mS movlw H'01' movwf tim0 WA0 movlw H'25' ; movlw d'25' movwf tim1 WA1 clrf tim2 WA2 nop decfsz tim2,F goto WA2 decfsz tim1,F goto WA1 decfsz tim0,F goto WA0 RETURN ;*********************************************************** ; EEPROM書き込み ;************************************************************ WRITE_EEPROM bsf STATUS,RP1 ; bsf STATUS,RP0 ; Bank 3 btfsc EECON1,WR ; Wait for write goto $-1 ; to complete bcf STATUS,RP1 ; bcf STATUS,RP0 ; Bank 0 movf data_ee_addr,W ; Data Memory Address bsf STATUS,RP1 ; Bank 2 movwf EEADR ; to write bcf STATUS,RP1 ; Bank 0 movf data_ee_data,W ; Data Memory Value bsf STATUS,RP1 ; Bank 2 movwf EEDATA ; to write bsf STATUS,RP0 ; Bank 3 bcf EECON1,EEPGD ; Point to DATA memory bsf EECON1,WREN ; Enable writes ; bcf INTCON,GIE ; Disable INTs. movlw h'55' ; movwf EECON2 ; Write 55h movlw h'AA' ; movwf EECON2 ; Write AAh bsf EECON1,WR ; Set WR bit to begin write btfsc EECON1,WR goto $-1 ; bsf INTCON,GIE ; Enable INTs. bcf EECON1,WREN ; Disable writes bcf STATUS,RP1 ; bcf STATUS,RP0 ; Bank 0 return ;*********************************************************** ; EEPROM読み出し ;************************************************************ READ_EEPROM movf data_ee_addr,W ; Data Memory Address bsf STATUS,RP1 ; Bank 2 movwf EEADR ; to read bsf STATUS,RP0 ; Bank 3 bcf EECON1,EEPGD ; Point to Data memory bsf EECON1,RD ; EE Read bcf STATUS,RP0 ; Bank 2 movf EEDATA,W ; W = EEDATA bcf STATUS,RP1 ; bcf STATUS,RP0 ; Bank 0 return ;*******************Initialization subroutine********************* ; This routine initializes the MSSP module ; for I2C Master mode, with a 100 kHz clock. ;***************************************************************** InitI2C bsf STATUS,RP0 ; Select Bank 01 clrf SSPSTAT ; Disable SMBus inputs bsf SSPSTAT,SMP ; Disable slew rate control ; movlw 0x18 ; Load 0x18 into WREG(for OSC 10MHz) ; movwf SSPADD ; Setup 100 kHz I2C clock movlw 0x63 ; Load 0x63 into WREG(for OSC 10MHz) movwf SSPADD ; Setup 400 kHz I2C clock ; movlw 0xF9 ; Load 0xF9 into WREG(for OSC 10MHz) ; movwf SSPADD ; Setup 1 MHz I2C clock clrf SSPCON2 ; Clear control bits bcf STATUS,RP0 ; Select Bank 00 movlw b'00101000' movwf SSPCON ; Enable SSP, select I2C Master mode bcf PIR1,SSPIF ; Clear SSP interrupt flag bcf PIR2,BCLIF ; Clear Bit Collision flag return ;*******************Start bit subroutine************************** ; This routine generates a Start condition ; (high-to-low transition of SDA while SCL ; is still high. ;***************************************************************** BSTART bcf STATUS,RP1 bcf STATUS,RP0 ; Select Bank 00 bcf PIR1,SSPIF ; Clear SSP interrupt flag bsf STATUS,RP0 ; Select Bank 01 bsf SSPCON2,SEN ; Generate Start condition bcf STATUS,RP0 ; Select Bank 00 bstart_wait btfss PIR1,SSPIF ; Check if operation completed goto bstart_wait ; If not, keep checking return ;*******************Restart bit subroutine************************** ; This routine generates a Repeated Start ; condition (high-to-low transition of SDA ; while SCL is still high. ;***************************************************************** BRESTART bcf STATUS,RP1 bcf STATUS,RP0 ; Select Bank 00 bcf PIR1,SSPIF ; Clear SSP interrupt flag bsf STATUS,RP0 ; Select Bank 01 bsf SSPCON2,RSEN ; Generate Restart condition bcf STATUS,RP0 ; Select Bank 00 brestart_wait btfss PIR1,SSPIF ; Check if operation completed goto brestart_wait ; If not, keep checking return ;*******************Stop bit subroutine*************************** ; This routine generates a Stop condition ; (low-to-high transition of SDA while SCL ; is still high. ;***************************************************************** BSTOP bcf STATUS,RP1 bcf STATUS,RP0 ; Select Bank 00 bcf PIR1,SSPIF ; Clear SSP interrupt flag bsf STATUS,RP0 ; Select Bank 01 bsf SSPCON2,PEN ; Generate Stop condition bcf STATUS,RP0 ; Select Bank 00 bstop_wait btfss PIR1,SSPIF ; Check if operation completed goto bstop_wait ; If not, keep checking return ;*******************Data transmit subroutine********************** ; This routine transmits the byte of data ; stored in 'datao' to the serial EEPROM ; device. Instructions are also in place ; to check for an ACK bit, if desired. ; Just replace the 'goto' instruction, ; or create an 'ackfailed' label, to provide ; the functionality. ;***************************************************************** TX bcf STATUS,RP1 bcf STATUS,RP0 ; Select Bank 00 bcf PIR1,SSPIF ; Clear SSP interrupt flag movf datao,W ; Copy datao to WREG movwf SSPBUF ; Write byte out to device tx_wait btfss PIR1,SSPIF ; Check if operation completed goto tx_wait ; If not, keep checking ; bsf STATUS,RP0 ; Select Bank 01 ; btfsc SSPCON2,ACKSTAT ; Check if ACK bit was received ; goto ackfailed ; This executes if no ACK received return ;*******************Data receive subroutine*********************** ; This routine reads in one byte of data from ; the serial EEPROM device, and stores it in ; 'datai'. It then responds with either an ; ACK or a NO ACK bit, depending on the value ; of 'ACKDT' in 'SSPCON2'. ;***************************************************************** RX bcf STATUS,RP1 bcf STATUS,RP0 ; Select Bank 00 bcf PIR1,SSPIF ; Clear SSP interrupt flag bsf STATUS,RP0 ; Select Bank 01 bsf SSPCON2,RCEN ; Initiate reception of byte bcf STATUS,RP0 ; Select Bank 00 rx_wait btfss PIR1,SSPIF ; Check if operation completed goto rx_wait ; If not, keep checking movf SSPBUF,W ; Copy byte to WREG movwf datai ; Copy WREG to datai bcf PIR1,SSPIF ; Clear SSP interrupt flag bsf STATUS,RP0 ; Select Bank 01 bsf SSPCON2,ACKEN ; Generate ACK/NO ACK bit bcf STATUS,RP0 ; Select Bank 00 rx_wait2 btfss PIR1,SSPIF ; Check if operation completed goto rx_wait2 ; If not, keep checking return ;*******************Byte write test subroutine******************** ; This routine tests the byte write feature ; of the serial EEPROM device. It will write ; 1 byte of data to the device at address 0x5AA5. ;***************************************************************** ByteWrite movwf datasave movwf dataw call BSTART ; Generate Start condition ; Send control byte bcf STATUS,RP0 ; Select Bank 00 movlw WRITE_ADDR ; Load control byte for write movwf datao ; Copy to datao for output call TX ; Send control byte to device ; Send word address high byte bcf STATUS,RP0 ; Select Bank 00 ; movlw 0x5A ; Load 0x5A for word address movf address_h,W ; Load Address High Byte movwf datao ; Copy to datao for output call TX ; Send word address low byte bcf STATUS,RP0 ; Select Bank 00 ; movlw 0xA5 ; Load 0xA5 for word address movf address_l,W ; Load Address Low Byte movwf datao ; Copy to datao for output call TX ; Send word address to device ; Send data byte bcf STATUS,RP0 ; Select Bank 00 ; movlw 0xAA ; Load 0xAA for data byte movf dataw,W ; Load data movwf datao ; Copy to datao for output call TX ; Send data byte to device call BSTOP ; Generate Stop condition call Poll ; Poll for write completion movf datasave,W return ;*******************Byte read test subroutine********************* ; This routine tests the byte read feature ; of the serial EEPROM device. It will read ; 1 byte of data at address 0x5AA5 from the device. ;***************************************************************** ByteRead call BSTART ; Generate Start condition ; Send control byte bcf STATUS,RP0 ; Select Bank 00 movlw WRITE_ADDR ; Load control byte for write movwf datao ; Copy to datao for output call TX ; Send control byte to device ; Send word address high byte bcf STATUS,RP0 ; Select Bank 00 ; movlw 0x5A ; Load 0x5A for word address movf address_h,W ; Load Address Low Byte movwf datao ; Copy to datao for output call TX ; Send high byte to device ; Send word address low byte bcf STATUS,RP0 ; Select Bank 00 ; movlw 0xA5 ; Load 0xA5 for word address movf address_l,W ; Load Address Low Byte movwf datao ; Copy to datao for output call TX ; Send word address to device call BRESTART ; Generate Restart condition ; Send control byte bcf STATUS,RP0 ; Select Bank 00 movlw READ_ADDR ; Load control byte for read movwf datao ; Copy to datao for output call TX ; Send control byte to device ; Read data byte bsf STATUS,RP0 ; Select Bank 01 bsf SSPCON2,ACKDT ; Select to send NO ACK bit call RX ; Read data byte from device call BSTOP ; Generate Stop condition movf datai,W return ;*******************Sequential read test subroutine*************** ; This routine tests the sequential read feature ; of the serial EEPROM device. It will read 16 ; bytes of data to the device starting at ; address 0x50, one byte after another. ;***************************************************************** SequentialRead bcf STATUS,RP0 ; Select Bank 00 movlw D'16' movwf bytecount ; Initialize counter to 16 bytes call BSTART ; Generate start bit ; Now send the control byte ; for a write, to set address bcf STATUS,RP0 ; Select Bank 00 movlw WRITE_ADDR movwf datao ; Copy control byte to buffer call TX ; Output control byte to device ; Send word address high byte bcf STATUS,RP0 ; Select Bank 00 clrf datao ; Load 0x00 into datao call TX ; Send high byte to device ; Send word address low byte bcf STATUS,RP0 ; Select Bank 00 movlw 0x50 ; Load 0x50 for word address movwf datao ; Copy to datao for output call TX ; Send word address to device call BRESTART ; Generate another start bit ; to switch to read mode bcf STATUS,RP0 ; Select Bank 00 movlw READ_ADDR movwf datao ; Copy control byte to buffer call TX ; Output control byte to device rxbyte ; Finally, read the data byte bcf STATUS,RP0 ; Select Bank 00 decfsz bytecount,F ; Check if finished looping goto continue ; If not finished, keep going bsf STATUS,RP0 ; Select Bank 01 bsf SSPCON2,ACKDT ; Otherwise, select to send NO ACK bit call RX ; and input final byte from device call BSTOP ; Generate stop bit return continue bsf STATUS,RP0 ; Select Bank 01 bcf SSPCON2,ACKDT ; Select to send ACK bit call RX ; Input data from device goto rxbyte ; Continue looping ;*******************Acknowledge Polling subroutine**************** ; This subroutine polls the EEPROM device ; for an ACK bit, which indicates that the ; internal write cycle has completed. Code ; is in place for a timeout routine, just ; uncomment the 'goto TimedOut' line, and ; provide a 'TimedOut' label. ;***************************************************************** Poll bcf STATUS,RP0 ; Select Bank 00 movlw D'40' movwf pollcnt ; Set max polling times to 40 polling call BRESTART ; Generate start bit bcf STATUS,RP0 ; Select Bank 00 movlw WRITE_ADDR ; Now send the control byte movwf datao ; Copy control byte to buffer call TX ; Output control byte to device bsf STATUS,RP0 ; Select Bank 01 btfss SSPCON2,ACKSTAT ; Was the ACK bit low? goto exitpoll ; If yes, stop polling ; If no, check if polled 40 times bcf STATUS,RP0 ; Select Bank 00 decfsz pollcnt,F ; Is poll counter down to zero? goto polling ; If no, poll again ; goto TimedOut ; If yes, part didn't respond ; in time, so take action exitpoll call BSTOP ; Generate stop bit return ; --------------------------------------------------------- ; ; Soft Serial send ; ; --------------------------------------------------------- SoftTx movwf txd bcf PORTSOFTTX ; PORTSOFTTX ビットクリア movlw BTIME ; スタートビット movwf rs r1tx10 decfsz rs,F goto r1tx10 movlw 8 movwf cn ; ビット位置 nop r1tx11 rrf txd,F nop btfss STATUS,C ; ポートに出力 bcf PORTSOFTTX btfsc STATUS,C bsf PORTSOFTTX movlw BTIME movwf rs r1tx12 decfsz rs,F goto r1tx12 ; 1ビットのウエイト decfsz cn,F goto r1tx11 ; 8ビット分繰り返し nop nop nop nop nop nop bsf PORTSOFTTX ; PORTSOFTTX を1に ストップビット movlw BTIME movwf rs r1tx13 decfsz rs,F goto r1tx13 ; 1ビットのウエイト return ; 1文字送信終了、戻る END