Title "Read12.asm 7/02/2002 ;Modified from read4k.asm code for use with 12bit PIC16C773 in logger, July 1, 2002 ;Modifications by Brooks McKinney ; list p=16c73a ;-------------------------------------------------------------------------- ;READER program ;This program uses PORT_B output to signal the datalogger to start, but also ;as a debugging output ;For HI value on Pin ; 28 RB7 start ; 27 RB6 ckdata ; 26 RB5 w/28 pulsing=sndata ; 25 RB4 cmand ; 24 RB3 setrd ; 23 RB2 intlz ; 22 RB1 (on at start command) ;-------------------------------------------------------------------------- ;----- Parameters---------------------------------------------------------- W equ H'0000' F equ H'0001' NOTOK equ H'00' ;NOT OK command code OK equ H'01' ;OK command code DAT equ H'02' ;DATa command code REA equ H'03' ;REAd command code INI equ H'04' ;INIntialize command code STA equ H'05' ;STArt command code EXI equ H'06' ;EXIt command code STP equ H'07' ;Exit sndata loop ;----- Register Files------------------------------------------------------ TMR0 EQU H'0001' STATUS EQU H'0003' INTCON EQU H'000B' PIR1 EQU H'000C' SSPBUF EQU H'0013' SSPCON EQU H'0014' RCSTA EQU H'0018' TXREG EQU H'0019' RCREG EQU H'001A' ;OPTION EQU H'0081' PIE1 EQU H'008C' PCON EQU H'008E' PR2 EQU H'0092' TXSTA EQU H'0098' SPBRG EQU H'0099' PORT_B EQU H'06' TRIS_B EQU H'86' PORT_C EQU H'07' TRIS_C EQU H'87' ;----- STATUS Bits -------------------------------------------------------- RP1 EQU H'0006' RP0 EQU H'0005' Z EQU H'0002' ;----- INTCON Bits -------------------------------------------------------- GIE EQU H'0007' PEIE EQU H'0006' T0IE EQU H'0005' INTE EQU H'0004' RBIE EQU H'0003' T0IF EQU H'0002' INTF EQU H'0001' RBIF EQU H'0000' ;----- PIR1 Bits ---------------------------------------------------------- ADIF EQU H'0006' RCIF EQU H'0005' TXIF EQU H'0004' SSPIF EQU H'0003' CCP1IF EQU H'0002' TMR2IF EQU H'0001' TMR1IF EQU H'0000' ;----- RCSTA Bits --------------------------------------------------------- SPEN EQU H'0007' RX9 EQU H'0006' RC9 EQU H'0006' ; Backward compatibility only NOT_RC8 EQU H'0006' ; Backward compatibility only RC8_9 EQU H'0006' ; Backward compatibility only SREN EQU H'0005' CREN EQU H'0004' FERR EQU H'0002' OERR EQU H'0001' RX9D EQU H'0000' RCD8 EQU H'0000' ; Backward compatibility only ;----- OPTION Bits -------------------------------------------------------- NOT_RBPU EQU H'0007' INTEDG EQU H'0006' T0CS EQU H'0005' T0SE EQU H'0004' PSA EQU H'0003' PS2 EQU H'0002' PS1 EQU H'0001' PS0 EQU H'0000' ;----- PIE1 Bits ---------------------------------------------------------- ADIE EQU H'0006' RCIE EQU H'0005' TXIE EQU H'0004' SSPIE EQU H'0003' CCP1IE EQU H'0002' TMR2IE EQU H'0001' TMR1IE EQU H'0000' ;----- TXSTA Bits --------------------------------------------------------- CSRC EQU H'0007' TX9 EQU H'0006' NOT_TX8 EQU H'0006' ; Backward compatibility only TX8_9 EQU H'0006' ; Backward compatibility only TXEN EQU H'0005' SYNC EQU H'0004' BRGH EQU H'0002' TRMT EQU H'0001' TX9D EQU H'0000' TXD8 EQU H'0000' ; Backward compatibility only ;------------------------------------------------------- ;EEPROM REGISTERS FLAG equ 20 ; Common flag bits register EEPROM equ 21 ; Bit buffer ERCODE equ 22 ; Error code (to indicate bus status) LOEADR equ 23 ; >>>Lo byte of eeprom mem address register HIEADR equ 2C ; >>>Hi byte of eeprom mem address register LODATI equ 24 ; Lo byte of data input register HIDATI equ 30 ; Hi byte of data input register LODATO equ 25 ; Lo byte of data output register HIDATO equ 31 ; Hi byte of data output register SLAVE equ 26 ; Device address (1010xxx0) TXBUF equ 27 ; TX buffer RXBUF equ 28 ; RX buffer COUNT equ 29 ; Bit counter TEMP equ 2A ; Temporary storage TEMP1 equ 2B ; More Temporary storage KOUNT equ 2D ;Serial Registers BYTEIN equ 2E ;register for incoming serial data BYTEOUT equ 2F ;register for outgoing serial data DATBUF equ 32 ;eeprom data write buffer ;----------------------------------------------------------------------------- ; Bit Assignments ;----------------------------------------------------------------------------- ; FLAG Bits ERRORFLG equ 0 ; Error flag ; EEPROM Bits DI equ 7 ; EEPROM input DO equ 6 ; EEPROM output ; I2C Device Bits SDA equ 4 ; RC4, data in/out SCL equ 3 ; RC3, serial clock ;----------------------------------------------------------------------------- org 00h ;Reset Vector goto start ; org 05h ;Beginning of program ;-------------------------------------------------------------------------- ;Begin Main Program ;-------------------------------------------------------------------------- start ;Set up RS232 to Host bsf STATUS,RP0 ;select bank 1 movlw 0h ;put 00000000 in w movwf TRIS_B ;Config PORT_B as all outputs movlw .25 ;2400 baud @4MHz movwf SPBRG movlw b'10100000' ;Async, Low baud rate movwf TXSTA bcf STATUS,RP0 ;select bank 0 movlw B'00111011' ; I2C master mode enabled movwf SSPCON clrf HIEADR clrf LOEADR movlw B'10100000' ; EEPROM I2C address movwf SLAVE movlw b'10000000' movwf PORT_B ;PIN 28 HI ;>FLOWCHART#1 call rcbyte ;Read in byte from serial port host, data in bytein movlw OK ;OK code in w subwf BYTEIN, W ;subtract, result 0 if bytein=ok btfsc STATUS, Z ;if w=0 go on, if not try again goto cont1 ;go here if bytein=ok call txnot ;send notok code back to host goto start ;loop back to try again cont1 movlw b'01000000' ;PIN 27 HI movwf PORT_B ;>FLOWCHART#2 call txok ;send OK code to host ckdat ;>FLOWCHART#3 clrf HIEADR clrf LOEADR call rcbyte ;wait for host DAT code; back here if NOTOK read movlw DAT ;load DAT code to w subwf BYTEIN,W ;result w=0 if rec byte is DAT ;>FLOWCHART#4 btfsc STATUS, Z ;if DAT, w=0, z is set do goto goto sndata ;go here if bytein=DAT call txnot ;if not DAT send NotOk code goto ckdat ;loop to try again sndata ;>FLOWCHART#5 clrf PORT_B ;all PORT_B Pins off, pulse 28 and 26, see below movlw B'10100000' ;EEPROM I2C address movwf PORT_B ;PIN 28 and 26 on bsf STATUS,RP0 ;select bank 1 movlw 0FFh ;Setup PORT_C as all inputs movwf TRIS_C ;configure PORT_C as all input bcf STATUS,RP0 call txok ;send ok loop1 ;>FLOWCHART#6 call rcbyte ;wait for signal byte from reader movlw STP ;put stop code in w subwf BYTEIN,W ;subtract incoming, zero bit set if result 0 btfsc STATUS,Z ;check zero bit, continue sending data if clear, done if set goto eod ;go here if STP code received, end sending data call RDBYTES ;Input byte from EEPROM movf LODATI,W ;Get lo byte from eeprom ;movf LOEADR,W ;DEBUG-remove and use line above movwf BYTEOUT ;put lo byte from EEPROM in serial out buffer call txbyte ;send lo byte to host movf HIDATI,W ;get hi byte from eeprom ;movf HIEADR,W ;DEBUG-remove and use line above movwf BYTEOUT ;put hi byte from eeprom in serial out buffer call rcbyte ;wait for byte from host, no checking call txbyte ;send hi byte to host**** incfsz LOEADR,F ;increment address goto loop1 ;send another unless LOEADR=0 incf HIEADR,F ;if LOEADR=0, incrment HIEADR movlw h'40' ;put max HIEADR in w --changed from 2K version subwf HIEADR,W ;subtract W from HIEADR, if 0 done at end of data btfss STATUS,Z ;if bit is set, done goto loop1 ;if bit clear, not 0, not done, read next goto cmand ;>FLOWCHART#7 ;call rcbyte ;wait for byte to come in, no checking ;movlw h'00' ;put 0 in w ;movwf BYTEOUT ;put in output buffer ;call txbyte ;send to host--first of end of data markers ;comf BYTEOUT,F ;set BYTEOUT to h'FF' ;>FLOWCHART#8 ;call rcbyte ;wait for byte to come in, no checking ;call txbyte ;send to host, second of end of data markers eod call txok ;respond to stop data handshake from host ;-------------Data sent, wait for commands-------------------------------- ;Reader wait for one of three command codes: ; NOTOK = Problem with data, go back and reread ; REA = Set REAd flag in logger EEPROM ; INI = Do logger initialization ;------------------------------------------------------------------------- ; cmand clrf PORT_B ;clear PORT_B pins movlw b'00010000' ;Turn PIN 25 on movwf PORT_B ;FLOWCHART#9 call rcbyte ;wait for byte from host, data in bytein movlw REA ;REA code in w subwf BYTEIN, W ;subtract, result 0 if bytein=REA btfsc STATUS, Z ;if bytein=REA this bit set goto setread ; movlw INI ;INI code in w subwf BYTEIN, W ;subtract, result 0 if bytein=INI btfsc STATUS, Z ;if bytein=INI this bit set goto setini ; movlw DAT ;falls thru to here, put code in w movwf BYTEOUT ;move to serial out buffer ;>FLOWCHART#10 call txbyte ;send code back to host goto ckdat ;go back to chkdata, if error in code does this! setread ;>FLOWCHART#11 clrf PORT_B ;Clear PORT_B movlw b'00001000' ;PIN 24 HI clrf HIEADR ;clear HIEADR, select EEPROM bank 0 movlw .5 ;location of LOEADR in EEPROM movwf LOEADR ;put into EEPROM subroutine addr buffer movlw .1 ;value for read movwf LODATO ;put in EEPROM output buffer clrf HIDATO call WRBYTES ;write value to EEPROM movlw REA ;put code in w movwf BYTEOUT ;move to serial out buffer call txbyte ;send code back clrf LOEADR goto cmand ;back for next command setini ;FLOWCHART#12 bcf STATUS,RP0 movlw INI movwf BYTEOUT call txbyte clrf PORT_B ;clear PORT_B movlw b'00000100' ;PIN 23 HI movwf PORT_B clrf HIEADR ;clear hi byte of eeprom address clrf LOEADR ;clear lo byte of eeprom address clrf HIDATO ;clear hi byte of eeprom storage--zero for all initial values nxtdat ;>FLOWCHART#13 call rcbyte ;get first databyte movf BYTEIN,W ;move data to w movwf LODATO ;move data to EEPROM output buffer wrtdat call WRBYTES ;write EEPROM call RDBYTES ;read back data movf LODATI,W ; movwf BYTEOUT cont2 ;should time out in that case. call txbyte ;send byte back to host incfsz LOEADR,F ;increment address movlw .16 ;NEW put max header value in w subwf LOEADR,W ;Test, result=0 if all header done btfss STATUS,Z goto nxtdat ;get another unless LOEADR=0 movlw h'10' ; movwf HIDATO clrf LODATO call WRBYTES ;Write EOD marker to position 16 clrf LOEADR clrf HIDATO ;>FLOWCHART#15 call rcbyte ;wait for STArt byte from host movlw STA ;put STArt code in w subwf BYTEIN,w ;subtract, w=0 if BYTEIN=STArt code btfss STATUS,Z ;bit set if BYTEIN=STA goto setini ;send go back to setini, sends ini code and waits clrf PORT_B movlw b'00000010' ;send RB1 high movwf PORT_B movlw h'FF' movwf KOUNT PnDly call Delay call Delay call Delay call Delay call Delay call Delay call Delay call Delay decfsz KOUNT goto PnDly call txok clrf PORT_B ;FLOWCHART#16 xloop goto xloop ;terminal loop--turns on startpin. Manually reset processor. ;----------------------------------------------------------------------- ;END main program ;----------------------------------------------------------------------- ;SUBROUTINES ;-------------------------------------------------------------------------- ;TXOK: Send an OK code out serial port ;-------------------------------------------------------------------------- txok movlw OK ;OK code in w movwf BYTEOUT call txbyte ;send OK return ;-------------------------------------------------------------------------- ;TXNOT: Send a NOTOK code out serial port ;-------------------------------------------------------------------------- txnot movlw NOTOK ;NOTOK code in w movwf BYTEOUT call txbyte ;send NOTOK return ;-------------------------------------------------------------------------- ;RCBYTE: get one byte from serial port, result in BYTEIN ;-------------------------------------------------------------------------- rcbyte bcf RCSTA, CREN ;clear any errors movlw b'10010000' ;Enable continous reception movwf RCSTA listen btfss PIR1, RCIF ;RCIF set when byte received goto listen movlw 06h ;Mask out unwanted bits andwf RCSTA,W ;Check for errors btfsc STATUS,Z goto dataok ;No error bcf RCSTA, CREN ;Error, clear error bsf RCSTA, CREN ; goto listen ;try again dataok movf RCREG,W movwf BYTEIN bcf RCSTA, CREN ;disable receive return ;-------------------------------------------------------------------------- ;TXBYTE: send one byte out serial port ;-------------------------------------------------------------------------- txbyte bsf STATUS,RP0 ;select bank1 bsf TXSTA, TXEN ;enable send bcf STATUS,RP0 ;select bank0 movf BYTEOUT,W ;put data in w movwf TXREG ;put data in tx register and start send return ;--------------------------------------------------------------------------- ;EEPROM READ/WRITE SUBROUTINES ;Original code from Microchip ;Modified by DB McKinney for the 24LC256 EEPROM; addressing in HIEADR and ADDR. ;See note inn program header on organization--two parallel banks, one for lo byte, one for hi ;All reads and writes are two bytes, one from each bank, address differs only in bit 6 of HIEADR ;----------------------------------------------------------------------------------- ;HIEADR is high byte of the EEPROM memory address ;LOEADR is low byte of the EEPROM memory address ;LODATO is low byte data OUT register, used by WRBYTES ;HIDATO is hi byte data OUT register, used by WRBYTES ;LODATI is low byte data IN register, used by RDBYTES ;HIDATI is hi byte data IN regsiter, used by RDBYTES ;SLAVE is Device address ;DATBUF is a register for swapping hi/lo bytes to the read/write routines ;----------------------------------------------------------------------------- ; BYTE-WRITE, write one byte to EEPROM deviced ;----------------------------------------------------------------------------- ; Input : LODATO = lo data byte to be written ; HIDATO = hi data byte to be written ; HIEADR = high byte of EEPROM memory address ; LOEADR = low byte of EEPROM memory address ; SLAVE = device address (1010xxx0) ; Output : Data written to EEPROM device ;----------------------------------------------------------------------------- WRBYTES ;EEPROM CODE FOR 24LC256 EEPROM, writes a high and low byte for each call TOPWRB bcf STATUS,RP0 ; Which byte to write, hi or lo? btfsc HIEADR,6 ; If bit 6 clear, data is low byte movf HIDATO,W ; If bit 6 set, put hi byte in w btfss HIEADR,6 ; If bit 6 is set, data is hi byte movf LODATO,W ; If bit 6 clear, data is lo byte movwf DATBUF ; Put data in buffer movf SLAVE,W ; Put SLAVE cntrl byte in w movwf TXBUF ; Move modified full address to xmit buffer call BSTART ; Generate START bit call TX ; Output SLAVE address movf HIEADR,W ; Get high byte of mem address movwf TXBUF ; Load to output buffer call TX ; Send high part of mem address movf LOEADR,W ; Get low byte of mem address movwf TXBUF ; load in output buffer call TX ; Send lo byte of mem address movf DATBUF,W ; Load data byte to w movwf TXBUF ; load data byte into buffer call TX ; Output DATA and detect acknowledgement call BSTOP ; Generate STOP bit call Delay call Delay call Delay call Delay ;call WRDONE ; poll ack to see if write is completed btfsc HIEADR,6 ; Check to see if this is lo (clear) or hi (set) byte goto ENDWRB ; if bit is set, write cycle is done bsf HIEADR,6 ; Set bit 6 for hi data byte goto TOPWRB ; Loop back to do hi data byte ENDWRB bcf HIEADR,6 ; reset bit 6 for lo byte for return to program ; Call WRDONE Call Delay Call Delay Call Delay Call Delay return ;----------------------------------------------------------------------------- ; WRDONE Poll eeprom to see if write cycle is done >>>added for 12bit version ; Currently link to it is commented out, see 8 lines above ;----------------------------------------------------------------------------- WRDONE bcf STATUS,RP0 movf SLAVE,W ; Put SLAVE cntrl byte in w movwf TXBUF ; Move modified full address to xmit buffer call BSTART ; Generate START bit call TX ; Output SLAVE address btfsc EEPROM,DI ; Check ack bit, LO if write done goto WRDONE ; loop back and try again return ; ;----------------------------------------------------------------------------- ; TRANSMIT 8 data bits subroutine ;----------------------------------------------------------------------------- ; Input : TXBUF ; Output : Data transmitted to EEPROM device ;----------------------------------------------------------------------------- TX bcf STATUS,RP0 movlw .8 ; Set counter for eight bits movwf COUNT TXLP bcf EEPROM,DO ; Default 0 bit out btfsc TXBUF,7 ; If shifted bit = 0, data bit = 0 bsf EEPROM,DO ; otherwise data bit = 1 call BITOUT ; Send bit bcf STATUS,RP0 rlf TXBUF ; Rotate TXBUF left skpc ; f(6) ---> f(7) bcf TXBUF,0 ; f(7) ---> carry skpnc ; carry ---> f(0) bsf TXBUF,0 decfsz COUNT ; 8 bits done? goto TXLP ; No. call BITIN ; Read acknowledge bit bcf STATUS,RP0 ;movlw 3 ;btfsc EEPROM,DI ; Check for acknowledgement ;call ERR ; No acknowledge from device ;bcf STATUS,RP0 retlw 0 ;----------------------------------------------------------------------------- ; Single bit data transmit from PIC to serial EEPROM ;----------------------------------------------------------------------------- ; Input : EEPROM register, bit DO ; Output : Bit transmitted over I2C ; Error bits set as necessary ;----------------------------------------------------------------------------- BITOUT btfss EEPROM,DO goto BIT0 bsf STATUS,RP0 bsf TRIS_C,SDA ; Output bit 0 movlw 2 bcf STATUS,RP0 btfsc PORT_C,SDA ; Check for error code 2 goto CLK1 call ERR goto CLK1 ; SDA locked low by device BIT0 bsf STATUS,RP0 bcf TRIS_C,SDA ; Output bit 0 nop nop ; Delay CLK1 bsf STATUS,RP0 bsf TRIS_C,SCL ; Attempt to set SCL high movlw 1 ; Error code 1 bcf STATUS,RP0 btfsc PORT_C,SCL ; SCL locked low? goto BIT2 ; No. call ERR ; Yes, set error BIT2 nop ; Timing delay nop nop bsf STATUS,RP0 bcf TRIS_C,SCL ; Return SCL to low bcf STATUS,RP0 retlw 0 ;----------------------------------------------------------------------------- ; BYTE-READ, read one byte from serial EEPROM device ;----------------------------------------------------------------------------- ; Input : LOEADR = lo byte of eeprom address ; HIEADR = hi byte of eeprom address ; LODATI = lo byte of eeprom data ; HIDATI = hi byte of eeprom data ; SLAVE = device address (1010xxx0) ; Output : LODATI = lo byte of data read from serial EEPROM ; HIDATI = hi byte of data read from serial EEPROM ;----------------------------------------------------------------------------- ; RDBYTES ;EEPROM CODE FOR 24LC256 EEPROM! TOPRDB bcf STATUS,RP0 movf SLAVE,W ; Get SLAVE or cntl byte, put in w movwf TXBUF ; Slave into xmit buffer (R/W = 0) call BSTART ; Generate START bit call TX ; Output SLAVE address. Check ACK. movf HIEADR,W ; Get high part of mem address movwf TXBUF ; put in buffer call TX ; send movf LOEADR,W ; Get lo part of mem address movwf TXBUF ; put in buffer call TX ; send call BSTART ; START READ (if only one device is bcf STATUS,RP0 ; connected to the I2C bus) movf SLAVE,W ; get Slave or Cntrl Byte and put in w movwf TXBUF ; move to TXBUF bsf TXBUF,0 ; Specify READ mode by setting bit0 (R/W = 1) call TX ; Output SLAVE address call RX ; READ in data and acknowledge call BSTOP ; Generate STOP bit bcf STATUS,RP0 movf RXBUF,W ; Save data from buffer btfsc HIEADR,6 ; If clear, low data byte in W goto HIGHDATA ; movwf LODATI ;put result in low data byte bsf HIEADR,6 ;set bit for high data byte goto TOPRDB HIGHDATA movwf HIDATI ;put result in hi data byte bcf HIEADR,6 ;Reset to low data byte address return ; ;----------------------------------------------------------------------------- ; RECEIVE eight data bits subroutine ;----------------------------------------------------------------------------- ; Input : None ; Output : RXBUF = 8-bit data received ;----------------------------------------------------------------------------- ; RX bcf STATUS,RP0 movlw .8 ; 8 bits of data movwf COUNT clrf RXBUF ; RXLP rlf RXBUF ; Shift data to buffer skpc bcf RXBUF,0 ; carry ---> f(0) skpnc bsf RXBUF,0 call BITIN bcf STATUS,RP0 btfsc EEPROM,DI bsf RXBUF,0 ; Input bit =1 decfsz COUNT ; 8 bits? goto RXLP bsf EEPROM,DO ; Set acknowledge bit = 1 call BITOUT ; to STOP further input retlw 0 ; ;----------------------------------------------------------------------------- ; Single bit receive from serial EEPROM to PIC ;----------------------------------------------------------------------------- ; Input : None ; Output : Data bit received ;----------------------------------------------------------------------------- ; BITIN bsf STATUS,RP0 bsf TRIS_C,SDA ; Set SDA for input bcf STATUS,RP0 bcf EEPROM,DI bsf STATUS,RP0 bsf TRIS_C,SCL ; Clock high movlw 1 bcf STATUS,RP0 btfsc PORT_C,SCL ; Skip if SCL is high goto BIT1 call ERR BIT1 bcf STATUS,RP0 btfss PORT_C,SDA ; Read SDA pin, for ACK low goto ACKOK bsf EEPROM,DI ; DI = 1 ACKOK bsf STATUS,RP0 nop ; Delay bcf TRIS_C,SCL ; Return SCL to low bcf STATUS,RP0 retlw 0 ;----------------------------------------------------------------------------- ; DELAY, Provide a 10.78mS delay ;----------------------------------------------------------------------------- ; Input : None ; Output : None ;----------------------------------------------------------------------------- Delay bcf STATUS,RP0 movlw h'20' ; movwf TEMP1 dly1 decfsz TEMP1 goto dly1 ;Total time = ~10mS retlw 0 ;----------------------------------------------------------------------------- ; START bit generation routine ;----------------------------------------------------------------------------- ; input : none ; output : initialize bus communication ;----------------------------------------------------------------------------- ; ;Generate START bit (SCL is high while SDA goes from high to low transition) ;and check status of the serial clock. BSTART bsf STATUS,RP0 bsf TRIS_C,SDA ; Make sure SDA is high bsf TRIS_C,SCL ; Set clock high movlw 1 ; Ready error status code 1 bcf STATUS,RP0 btfss PORT_C,SCL ; Locked? call ERR ; SCL locked low by device, flag error bsf STATUS,RP0 bcf TRIS_C,SDA ; SDA goes low during SCL high nop ; Timing adjustment, 1uS @4MHz bcf TRIS_C,SCL ; Start clock train bcf STATUS,RP0 RETLW 0 ;----------------------------------------------------------------------------- ; STOP bit generation routine ;----------------------------------------------------------------------------- ; Input : None ; Output : Bus communication, STOP condition ;----------------------------------------------------------------------------- ; ;Generate STOP bit (SDA goes from low to high during SCL high state) ;and check bus conditions. BSTOP bsf STATUS,RP0 bcf TRIS_C,SDA ; Return SDA to low bsf TRIS_C,SCL ; Set SCL high nop movlw 1 ; Ready error code 1 bcf STATUS,RP0 btfss PORT_C,SCL ; High? call ERR ; No, SCL locked low by device bsf STATUS,RP0 bsf TRIS_C,SDA ; SDA goes from low to high during SCL high movlw 4 ; Ready error code 4 btfss TRIS_C,SDA ; High? call ERR ; No, SDA bus not release for STOP bcf STATUS,RP0 retlw 0 ; ;----------------------------------------------------------------------------- ; Two wire/I2C - CPU communication error status table and subroutine ;----------------------------------------------------------------------------- ; input : W-reg = error code ; output : ERCODE = error code ; FLAG(ERROR) = 1 ; ; code error status mode ; ------- ------------------------------------------------------ ; 1 : SCL locked low by device (bus is still busy) ; 2 : SDA locked low by device (bus is still busy) ; 3 : No acknowledge from device (no handshake) ; 4 : SDA bus not released for master to generate STOP bit ;----------------------------------------------------------------------------- ; ;Subroutine to identify the status of the serial clock (SCL) and serial data ;(SDA) condition according to the error status table. Codes generated are ;useful for bus/device diagnosis. ; ERR bcf STATUS,RP0 btfss FLAG,ERRORFLG ; If not first error, do not change code movwf ERCODE ; Save error code bsf FLAG,ERRORFLG ; Set error flag retlw 0 end