Mikhail508 0 Newbie Poster

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

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.