I'm trying to program a PIC16F886 as a I2C slave device using the code from Microchip application note AN734. I've compiled this example source code using MPLab 7.6 and flashed my PICmicro with the image. Now I am trying to talk to the chip using the AARDVARK I2C/SPI TOTAL PHASE connector but am not able to establish communication. I am trying to write bytes to the slave address from the AARDVARK GUI. I have the SCL, SDA and GND pins of the PICmicro connected to the AARDVARK connector which theoretically should be enough for two way communication via the GUI but it is not working. I've tried writing different numbers of bytes and changing the bitrate. Perhaps the buffer size needs to be adjusted for the PIC16F886. If somebody can please point me in the right direction, it would be greatly appreciated.
Thank you,
~Mikhail
The code is as follows:
; Include Files
#include <p16f886.inc>
; Constant Definitions
#define NODE_ADDR 0x02
; Buffer Length Definition
#define RX_BUF_LEN 32
; Variable declarations
udata
WREGsave res 1
STATUSsave res 1
FSRsave res 1
PCLATHsave res 1
Index res 1 ; Index to receive buffer
Temp res 1 ;
RXBuffer res RX_BUF_LEN ; Holds rec'd bytes from master device.
; Vectors
START code
nop
goto Startup
nop ; 0x0002
nop ; 0x0003
goto ISR ; 0x0004
PROG code
; Macros
memset macro Buf_addr,Value,Length
movlw Length ; This macro loads a range of data memory
movwf Temp ; with a specified value. The starting
movlw Buf_addr ; address and number of bytes are also
movwf FSR ; specified.
SetNext movlw 40
movwf INDF
incf FSR, F
decfsz Temp, F
goto SetNext
endm
LFSR macro Address, Offset ; This macro loads the correct value
movlw Address ; into the FSR given an initial data
movwf FSR ; memory address and offset value.
movf Offset, W
addwf FSR, F
endm
; Main Code
Startup
bcf STATUS, RP1
bcf STATUS, RP0
Main clrwdt ; Clear the watchdog timer.
goto Main ; Loop forever.
; Interrupt Code
ISR
movwf WREGsave ; Save WREG
movf STATUS, W ; Get STATUS register
banksel STATUSsave ; Switch banks, if needed.
movwf STATUSsave ; Save the STATUS register
movf PCLATH, W ;
movwf PCLATHsave ; Save PCLATH
movf FSR, W ;
movwf FSRsave ; Save FSR
banksel PIR1
btfss PIR1, SSPIF ; Is this a SSP interrupt?
goto $ ; No, just trap here.
bcf PIR1, SSPIF ;
call SSP_Handler ; Yes, service SSP interrupt
banksel FSRsave
movf FSRsave
movwf FSR ; Restore FSR
movf PCLATHsave, W ;
movwf PCLATH ; Restore PCLATH
movf STATUSsave, W ;
movwf STATUS ; Restore STATUS
swapf WREGsave, F ;
swapf WREGsave, W ; Restore WREG
retfile ; Return from interrupt.
Setup
; Initializes program variables and peripheral registers.
banksel PCON
bsf PCON, NOT_POR
bsf PCON, NOT_BOR
banksel Index ; Clear various program variables
clrf Index
clrf PORTB
clrf PIR1
banksel TRISB
clrf TRISB
movlw 0x36 ; Setup SSP module for 7-bit
banksel SSPCON
movwf SSPCON ; address, slave mode
movlw NODE_ADDR
banksel SSPADD
movwf SSPADD
clrf SSPADD
banksel PIE1
bsf PIE1, SSPIE
bsf INTCON, PEIE ; Enable all peripheral interupts
bsf INTCON, GIE ; Enable global interrupts
bcf STATUS, RP0
return
SSP_Handler
banksel SSPSTAT
movf SSPSTAT, W ; Get the value of SSPSTAT
andlw b'00101101' ; Mask out unimportant bits in SSPSTAT
banksel Temp ; Put masked value in Temp
movwf Temp ; for comparison checking.
State1: ; Write operation, last byte was an
movlw b'00001001' ; address, buffer is full.
xorwf Temp, W ;
btfss STATUS, Z ; Are we in State1?
goto State2 ; No, check for next state.....
memset RXBuffer, O, RX_BUF_LEN ; Clear the receive buffer.
clrf Index ; Clear the buffer index
call ReadI2C ; Do a dummy read of the SSPBUF
return
State2: ; Write operation, last byte was data
movlw b'00101001' ; buffer is full.
xorwf Temp, W
btfss STATUS, Z ; Are we in State2?
goto State3 ; No, check for next state.....
LFSR RXBuffer, Index ; Point to the buffer.
call ReadI2C ; Get the byte from the SSP.
movwf INDF ; Put it in the buffer.
incf Index, F ; Increment the buffer pointer
movf Index, F ; Increment the buffer index
return
State3: ; Read operation, last byte was an
movlw b'00001100' ; address, buffer is empty.
xorwf Temp, W
btfss STATUS, Z ; Are we in State3?
goto State4 ; No, check for next state.....
clrf Index ; clear the buffer index.
LFSR RXBuffer, Index ; Point to the buffer
movf INDF, W ; Get the byte to SSPBUF
call WriteI2C ; Write the byte to SSPBUF
incf Index, F ; Increment the buffer index.
return
State4: ; Read operation, last byte was data,
movlw b'00101100' ; buffer is empty.
xorwf Temp, W
btfss STATUS, Z ; Are we in State4?
goto State5 ; No, check for next state.....
movf Index, W ; Get the current buffer index.
sublw RX_BUF_LEN ; Subtract the buffer length.
btfsc STATUS, Z ; Has the index exceeded the buffer length?
clrf Index ; Yes, clear the buffer index.
LFSR RXBuffer, Index ; Point to the buffer
movf INDF, W ; Get the byte
call WriteI2C ; Write to SSPBUF
incf Index, F ; Increment the buffer index.
return
State5:
movlw b'00101000' ; A NACK was received when transmitting
xorwf Temp, W ; data back from the master. Slave logic
btfss STATUS, Z ; is reset in this case. R_W = 0, D_A = 1
goto I2CErr ; and BF = 0
return
I2CErr
nop
banksel PORTB ; Something went wrong! Set LED
bsf PORTB, 7 ; and loop forever. WDT will reset
goto $ ; device, if enabled.
return
WriteI2C
banksel SSPSTAT
btfsc SSPSTAT, BF ; Is the buffer full?
goto WriteI2C ; Yes, keep waiting
banksel SSPCON ; No, continue.
DoI2CWrite
bcf SSPCON,WCOL ; Clear the WCOL flag
movwf SSPBUF ; Write the byte in WREG
btfsc SSPCON,WCOL ; Was there a write collision?
goto DoI2CWrite
bsf SSPCON, CKP ; Release the clock.
return
ReadI2C
banksel SSPBUF
movf SSPBUF,W ; Get the byte and put in WREG
return
end ; End of file
end
If somebody can please point me in the right direction, it would be greatly appreciated.
Thank you,
~Mikhail