Forums

i2c slave using PIC16F88. Need urgent help/opinion.

Started by Unknown October 13, 2005
Hi all,
  I am using PIC16F88 as an I2C slave. I have attached the code that I
used. From the Microchip MPLAB ICD 2, I find that I am able to detect
the start and stop conditions. But I find that SSPSTAT<BF> is not
getting set. The program is getting stuck in the "gnb" loop. From the
Microchip ICD2, I can see that SSPSTAT<S> and SSPSTAT<P> get set after
the Start and Stop condictions. But not the BF bit. Nothing changes
even if i enable the interrupts. Probably the address was not getting
matched. I am using BL233 to mimic a master. Please let me know what
mistake I am doing.

Thanking you,
Mallik.

	processor	16f88
	include		p16f88.inc
	__CONFIG	_CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_ON & _WRT_PROTECT_OFF
& _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_OFF & _WDT_OFF &
_HS_OSC
;
	org	0x00
	nop			;required for In-Circuit Debugger
;
;	initialize I/O
;
	bsf	STATUS,RP0
	movlw	b'11010010'	;RB0,RB2,RB3,RB5 are outputs
	movwf	TRISB
	bcf	STATUS,RP0
;
;	Initialize the I2C
;
	clrf	SSPCON
	movlw	0x36		;SSPEN + CKP + i2c slave mode 7 bit
	movwf	SSPCON

	movlw	0x38		;slave address for flash loader
	bsf	STATUS,RP0
	movwf	SSPADD

	clrf	SSPSTAT

;	bcf	INTCON,GIE	;interrupts off (for now)
	bsf	INTCON,GIE	;interrupts on (for now)
	banksel	PIE1		; Enable interrupts
	bsf	PIE1,SSPIE
	clrf	STATUS

test:
	call	gnb
	goto	test
;
;	Get Next Byte from I2C
;
;	exit:	C == 1 if Start condition was last received
;		C == 0 if Stop condiction received.
;		Z == 1 if Data was received
;
gnb:	bsf	STATUS,RP0
	btfss	SSPSTAT,BF	;check buffer full flag
	goto	gnb		;loop if byte not ready

	btfss	SSPSTAT,5
	bsf	STATUS,Z

	bcf	STATUS,RP0
	bcf	PIR1,SSPIF	;clear interrupt flag

	movf	SSPBUF,W	;get byte


	btfsc	SSPSTAT,S	;check start/repeated start condition
	goto	gnb2		;jump if start received

	return
;
;	get here if a START was received.
;
gnb2:	
	bsf	STATUS,C
	return

end

<mallik_kommaraju@yahoo.co.in> wrote in message
news:1129231041.728172.160130@g47g2000cwa.googlegroups.com...
> Hi all, > I am using PIC16F88 as an I2C slave. I have attached the code that I > used. From the Microchip MPLAB ICD 2, I find that I am able to detect > the start and stop conditions. But I find that SSPSTAT<BF> is not > getting set. The program is getting stuck in the "gnb" loop. From the > Microchip ICD2, I can see that SSPSTAT<S> and SSPSTAT<P> get set after > the Start and Stop condictions. But not the BF bit. Nothing changes > even if i enable the interrupts. Probably the address was not getting > matched. I am using BL233 to mimic a master. Please let me know what > mistake I am doing. > > Thanking you, > Mallik. > > processor 16f88 > include p16f88.inc > __CONFIG _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_ON & _WRT_PROTECT_OFF > & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_OFF & _WDT_OFF
&
> _HS_OSC > ; > org 0x00 > nop ;required for In-Circuit Debugger
You should have something like "goto Startup" here to skip over the interrupt vector at 0x004. Then put a "Startup" label at the beginning of your initialize I/O stuff.
> ; > ; initialize I/O > ; > bsf STATUS,RP0 > movlw b'11010010' ;RB0,RB2,RB3,RB5 are outputs > movwf TRISB > bcf STATUS,RP0
OK so far, but most people recommend using the Banksel macro to select your active bank. It's ok here, but later in your code, it's real confusing as to which bank is currently selected.
> ; > ; Initialize the I2C > ; > clrf SSPCON > movlw 0x36 ;SSPEN + CKP + i2c slave mode 7 bit > movwf SSPCON > > movlw 0x38 ;slave address for flash loader > bsf STATUS,RP0 > movwf SSPADD > > clrf SSPSTAT
You appear to be in the correct bank at the appropriate times above, but it was painful for me to figure that out. I had to use the datasheet and painstakingly lookup the info. Please document your bank switching better, for your own sanity.
> ; bcf INTCON,GIE ;interrupts off (for now) > bsf INTCON,GIE ;interrupts on (for now) > banksel PIE1 ; Enable interrupts > bsf PIE1,SSPIE
This was a deadly move. Enabling interrupts with no handler present is never going to help. BTW, it's usually better if you enable GIE after setting up the other xxxxIE flags. You should also probably clear the xxxxIF flags before enabling GIE as well. That way you don't immediately fly into an interrupt routine because the IF was previously set.
> clrf STATUS > > test: > call gnb > goto test > ; > ; Get Next Byte from I2C > ; > ; exit: C == 1 if Start condition was last received > ; C == 0 if Stop condiction received. > ; Z == 1 if Data was received > ; > gnb: bsf STATUS,RP0 > btfss SSPSTAT,BF ;check buffer full flag > goto gnb ;loop if byte not ready > > btfss SSPSTAT,5
Instead of "5", you could use "I2C_DATA" or even "D"
> bsf STATUS,Z > > bcf STATUS,RP0 > bcf PIR1,SSPIF ;clear interrupt flag > > movf SSPBUF,W ;get byte > > > btfsc SSPSTAT,S ;check start/repeated start condition
Instead of "S" you could use "I2C_START"
> goto gnb2 ;jump if start received > > return > ; > ; get here if a START was received. > ; > gnb2: > bsf STATUS,C > return > > end
I don't see anything obviously wrong with your code, as long as the device acting as master uses 7 bit addressing and the clock polarity that you selected. What are you using for your pull-up resistors? How long (physically) is your bus? I have never used the I2C slave mode of a PIC, so I can't offer much more help on that. I would turn of the interrupts though, that's certainly not going to help without an appropriate interrupt handler. I'm guessing that you probably need to be fiddling some bits in SSPSTAT and SSPCON (like SSPOV for example) after every transmission. Have you carefully read the datasheet 10 times yet? ;-) You have to read the entire description of the slave serial port, not just the tidbits about I2C slave mode. Your best bet is to find a working example on the net.