;--------------------------------------------------------------------- ;The I2C code below checks for 5 states: ;--------------------------------------------------------------------- ;State 1: I2C write operation, last byte was an address byte. ; ;SSPSTAT bits: S = 1, D_A = 0, R_W = 0, BF = 1 ; ;State 2: I2C write operation, last byte was a data byte. ; ;SSPSTAT bits: S = 1, D_A = 1, R_W = 0, BF = 1 ; ;State 3: I2C read operation, last byte was an address byte. ; ;SSPSTAT bits: S = 1, D_A = 0, R_W = 1, BF = 0 ; ;State 4: I2C read operation, last byte was a data byte. ; ;SSPSTAT bits: S = 1, D_A = 1, R_W = 1, BF = 0 ; ;State 5: Slave I2C logic reset by NACK from master. ; ;SSPSTAT bits: S = 1, D_A = 1, R_W = 0, BF = 0 ; ; For convenience, WriteI2C and ReadI2C functions have been used. ;---------------------------------------------------------------------- I2C_Slave_Handler bcf PIR1, SSPIF bsf STATUS, RP0 movfw SSPSTAT ; Get the value of SSPSTAT andlw b'00101101' ; Mask out unimportant bits in SSPSTAT bcf STATUS, RP0 movwf SSP_RAM_Temp ; Put masked value in SSP_RAM_Temp for comparison checking SSP_State1 ; Write operation, last bye was an address, buffer is full movlw b'00001001' xorwf SSP_RAM_Temp, w bnz SSP_State2 movfw SSPBUF ; Buffer auslesen und irgendwo reinschreiben movwf test1 btfss SSPCON, SSPOV ; Overflow? return bcf SSPCON, SSPOV ; Dann SSPOV loeschen und nochmal Buffer auslesen movfw SSPBUF movwf test1 return SSP_State2 movlw b'00101001' xorwf SSP_RAM_Temp, w bnz SSP_State3 movfw SSPBUF ; dasselbe wie bei State1 movwf test1 btfss SSPCON, SSPOV return bcf SSPCON, SSPOV movfw SSPBUF movwf test1 return SSP_State3 ; Erstes Byte auslesen movlw b'00001100' xorwf SSP_RAM_Temp, w bnz SSP_State4 movlw 0xAA call WriteI2C ; einfach irgendwas zum lesen return SSP_State4 movlw b'00101100' xorwf SSP_RAM_Temp, w bnz SSP_State5 movlw 0xAA call WriteI2C ; einfach irgendwas zum lesen return SSP_State5 ; State5 macht anscheinend nichts movlw b'00101000' xorwf SSP_RAM_Temp, w bnz I2CErr ; kein State getroffen, dann zu Error return I2CErr goto $ WriteI2C bsf STATUS, RP0 btfsc SSPSTAT, BF ; is the buffer full? goto WriteI2C ; yes, keep waiting bcf STATUS, RP0 ; No, continue DoI2CWrite bcf SSPCON, WCOL ; clear the WCOL flag movwf SSPBUF ; write the byte in WREG btfsc SSPCON, WCOL ; was ther a write collision? goto DoI2CWrite bsf SSPCON, CKP ; release the clock ReadI2C movfw SSPBUF return