Here a working snipet for I2C slave communication.

I2C write command will be received into variable array RxBuffer and RxBuffer[0] is used for the case select routine.
I2C read command will return content of variable array TxBuffer. So before reading you have to update the array in someways. The easy way is to write a command that will update the array TxBuffer with the values you need than you read them.

Array lenght can be changed, changing the constants "RxBufferLEN" & "TxBufferLEN"

Slave address can be changed changing the constant "I2Caddress".

A 20 MHz quartz is recommended.

Add your code in the correct place and you should not have problem.


Code:
'****************************************************************
'*  Name    : I2C_Slave                                         *
'*  Author  :                                                   *
'*  Notice  :                                                   *
'*          : All Rights Reserved                               *
'*  Date    : 03/01/2008                                        *
'*  Version : 1.0                                               *
'*  Notes   : I2C Slave with Pic16F876                          *
'*          :                                                   *
'****************************************************************

'-- set device & tris port config here (don't use SCL & SDA pins other than I2C) ----

DEFINE I2C_HOLD 1

'---------------- Alias pins -----------------------------------

SCLDIR              var TRISC.3 
SDADIR              var TRISC.4

'--------------- Define used register flags -------------------

SSPIF               VAR PIR1.3              ' SSP (I2C) interrupt flag
SSPIE               VAR PIE1.3 
BF                  VAR SSPSTAT.0           ' SSP (I2C) Buffer Full
R_W                 VAR SSPSTAT.2           ' SSP (I2C) Read/Write
D_A                 VAR SSPSTAT.5           ' SSP (I2C) Data/Address
CKP                 VAR SSPCON.4            ' SSP (I2C) SCK Release Control
SSPEN               VAR SSPCON.5            ' SSP (I2C) Enable
SSPOV               VAR SSPCON.6            ' SSP (I2C) Receive Overflow Indicator
WCOL                VAR SSPCON.7            ' SSP (I2C) Write Collision Detect

STAT_BF             VAR SSPSTAT.0           ' SSP (I2C) Buffer Full
STAT_RW             VAR SSPSTAT.2           ' SSP (I2C) Read/Write
STAT_DA             VAR SSPSTAT.5           ' SSP (I2C) Data/Address
CKE                 VAR SSPSTAT.6           ' SSP (I2C) Data/Address


'------------------- Rx Buffer defintion --------------------
RxBufferLEN         con 3           
RxBuffer            var byte[Rxbufferlen]
RxBufferIndex       var byte

'------------------ Tx Buffer defintion ----------------------
TxBufferLEN         con 3
TxBuffer            var byte[txbufferlen]
TxBufferIndex       var byte


'------------------ Define constants ------------------------
I2Caddress          CON $2                  ' Make address = 2




' --------- Define here your variables and alias ------------------




' -------------- Initialize I2C slave mode ------------------------

SCLDIR = 1                                  ' SCL must be an input before enabling interrupts
SDADIR = 1   
SSPADD = I2Caddress                         ' Set our address
SSPCON2.7 = 0                               ' General call address disabled
SSPCON = $36                                ' Set to I2C slave with 7-bit address
SSPSTAT = 0
SSPIE = 1 
SSPIF = 0 
RxBufferIndex = 0
TxBufferIndex = 0

'----------------- Initialization Done! -----------------------------



GoTo main


'------------------------- I2C subroutine  -------------------------------- 

i2cslave:                                   ' I2C slave subroutine
SSPIF = 0                                   ' Clear interrupt flag
IF R_W = 1 Then i2crd                       ' Read data from us
IF BF = 0 Then i2cexit                      ' Nothing in buffer so exit
IF D_A = 1 Then i2cwr                       ' Data for us (not address)
IF SSPBUF != I2Caddress Then i2cexit        ' Clear the address from the buffer
readcnt = 0                                 ' Mark as first read
GoTo i2cexit

i2cwr:                                      ' I2C write data to us
datain = SSPBUF                             ' Put buffer data into array
Rxbuffer[Rxbufferindex]=datain
rxbufferindex =rxbufferindex+1

if rxbufferindex=RxBufferLEN then           ' end of buffer transfer 
WrData=1
rxbufferindex=0
endif

GoTo i2cexit

i2crd:                                      ' I2C read data from us
IF D_A = 0 Then
TxBufferIndex = 0
EndIF

while STAT_BF : wend                        ' loop while buffer is full
wcol = 0                                    ' clear collision flag
SSPBUF = TxBuffer[TxBufferIndex]
while wcol 
wcol = 0
SSPBUF = TxBuffer[TxBufferIndex]
wend
CKP = 1                                     ' release clock, allowing read by master
TxBufferIndex = TxBufferIndex + 1           ' increment index
if TxBufferIndex = TxBufferlen then         ' all bytes have been tx
TxBufferIndex = 0                           ' reset index            
endif
             
i2cexit:
Return

' -------------------------end I2C subroutine  -------------------------------- 

Main:
IF SSPIF = 1 Then
GoSub i2cslave
EndIF

SSPOV = 0
WCOL = 0

Select case RBuffer[0]
'--------------------- Place here your case select code
end select

WrData=0  
GoTo Main


' ----------------- This space for your program code

End
Enjoy

Al.