Maker Pro
Maker Pro

SEEPROM reading with 18F series PicMicro

A

Alexander

Jan 1, 1970
0
Hi Ya All,

I'm trying to write a code that reads an I2C SEEPROM.
It should work as follow,
The "main" program sets I2CEEADDR, I2CEESLAVE and I2CEEDATA.
After that a call to start writing "Start_I2C_Read" will be issued.
Now the contents of the EEPROM will be read and placed in the Internal
EEPROM of the processor, until a maximum of bytes has been read or an end
(\0) character is read.

In the ISR a call to the specific ISR is implemented
Most of the code has been adapted from the AN of microchip
The writing and reading of the internal EEPROM works fine.
The code fails unfortunatly.

Some of the code is copied under here (the fault should be somewhere in this
code).
Could anyone please help me???

ThanX in Advance,

Alexander

#define FOSC D'4000000' ; define FOSC to PICmicro
#define I2CClock D'100000' ; define I2C bite rate
#define ClockValue (((FOSC/I2CClock)/4) -1) ;
;************************************************************
I2CBase equ 0x040

I2CEEADDR equ I2CBase+0x000 ; Address register
I2CEEDATA equ I2CBase+0x001 ; data to read/write
I2CEESLAVE equ I2CBase+0x002 ; Device address (1010xxxy)
I2CSTATE equ I2CBase+0x004 ;
; copy these variables for internal use (possibility to use a wait list)
I2CEEADDR_TEMP equ I2CBase+0x005 ; Address register
I2CEEDATA_TEMP equ I2CBase+0x006 ; data to read/write
I2CEESLAVE_TEMP equ I2CBase+0x007 ; Device address (1010xxxy)
I2C_DATA_CHAR equ I2CBase+0x008 ; buffer for the I2C character (currently
processing)
i2cState equ I2CBase+0x009

;EE_ADDR EQU I2CBase+d'09'
;EE_DATA EQU I2CBase+d'10'

I2C_STATUS equ I2CBase+0x010 ; status for external use should only be
modified in this file
#DEFINE I2C_buzzy I2C_STATUS,0 ; There's currently a data transfer from/to
this device in progress or it should be, not nescecerly bus-idle
#DEFINE I2C_full I2C_STATUS,1 ; The secondary buffer has been loaded
(queue full)
#DEFINE I2C_write_complete I2CSTATUS,2 ; A write operation has been
completed
#DEFINE I2Cread_complete I2CSTATUS,3 ; A read operation has been completed

#define StringEndChar '\0'
#define read_max_count 0x32

Start_I2C_Read
BSF I2C_full
CALL i2c_idle
BSF I2C_buzzy
CALL init_vars
BCF I2C_full
MOVFF I2CEEADDR_TEMP, DATA_EE_ADDR
MOVLW 0
MOVWF i2cState,0 ; retrieve current I2C state
CALL service_i2c
RETURN

; configure SSP for hardware master mode I2C
Init_I2c:
;----------------------------------------------------------------------
; ******************* INITIALIZE MSSP MODULE *******************
;----------------------------------------------------------------------
movlw ClockValue ; read selected baud rate
movwf SSPADD ; initialize I2C baud rate
bcf SSPSTAT,6 ; select I2C input levels
bcf SSPSTAT,7 ; enable slew rate

movlw b'00011000' ;
iorwf TRISC,f ; ensure SDA and SCL are inputs
movlw b'00111000' ;
movwf SSPCON1 ; Master mode, SSP enable
return ; return from subroutine

MOVLW 0x08
MOVWF SSPCON1
BSF SSPCON1,SSPEN
CLRF SSPCON2

bsf PIE2,BCLIE ; enable interrupt
bsf INTCON,PEIE ; enable peripheral interrupt

RETURN

;----------------------------------------------------------------------
; ***** INITIALIZE VARIABLES USED IN SERVICE_I2C FUNCTION ******
;----------------------------------------------------------------------
init_vars
MOVFF I2CEEADDR,I2CEEADDR_TEMP
MOVFF I2CEEDATA,I2CEEDATA_TEMP
MOVFF I2CEESLAVE,I2CEESLAVE_TEMP
RETURN

;----------------------------------------------------------------------
; *********************** I2C Service *************************
;----------------------------------------------------------------------
I2C_COMM; CODE
service_i2c
movlw high I2CJump ; fetch upper byte of jump table address
movwf PCLATH ; load into upper PC latch
movlw 0
andwf i2cState,w ; retrieve current I2C state
addlw low (I2CJump + 1) ; calc state machine jump addr into W
btfsc STATUS,C ; skip if carry occured
incf PCLATH,f ; otherwise add carry
I2CJump ; address were jump table branch occurs, this addr also used in fill
movwf PCL ; index into state machine jump table
; jump to processing for each state = i2cState value for each state
goto WrtStart ; write start sequence = 0
goto SendWrtAddr ; write address, R/W=1 = 1
goto WrtAckTest ; test ack,write data = 2
goto WrtStop ; do stop if done = 3

goto ReadStart ; Read start sequence = 4
goto SendReadAddr ; Read address, R/W=0 = 5
goto ReadAckTest ; test acknowledge after address = 6
goto ReadData ; read more data = 7
goto ReadStop ; generate stop sequence = 8


I2CJumpEnd
; Fill (return), (I2CJump-I2CJumpEnd) + i2cSizeMask


;----------------------------------------------------------------------
; ******************* Generic I2C Functions ***********************
;----------------------------------------------------------------------
; test for i2c bus idle state and wait to get clear
i2c_idle
btfsc SSPSTAT,R_W ; test if transmit is in progress
goto $ - 2 ; module busy so wait
movf SSPCON2,w ; get copy of SSPCON2 for status bits
andlw 0x1F ; mask out non-status bits
btfss STATUS,Z ; test for zero state, if Z set, bus is idle
goto $ - 6 ; bus is busy so test again
return ; return to calling routine
;----------------------------------------------------------------------
; ********************* Write data to Slave *********************
;----------------------------------------------------------------------
WrtStart
SendWrtAddr
WrtAckTest
WrtData
WrtStop
;----------------------------------------------------------------------
; ********************* Read data from Slave *********************
;----------------------------------------------------------------------
; Generate I2C start condition [ I2C STATE -> 4 ]
ReadStart
incf i2cState,f ; update I2C state variable
bsf SSPCON2,SEN ; initiate I2C bus start condition
return ;
; Generate I2C address write (R/W=1) [ I2C STATE -> 5 ]
SendReadAddr
bsf STATUS,C ; ensure cary bit is SET
rlCf I2CEEADDR_TEMP,w ; compose 7 bit address
incf i2cState,f ; update I2C state variable
movwf SSPBUF ; initiate I2C bus write condition
return
; Test acknowledge after address write [ I2C STATE -> 6 ]
ReadAckTest
btfss SSPCON2,ACKSTAT ; test for not acknowledge from slave
goto StartReadData ; good ack, go issue bus read
; bsf eflag_event,ack_error ; set ack error flag
clrf i2cState ; reset I2C state variable
bsf SSPCON2,PEN ; initiate I2C bus stop condition
return
StartReadData
bsf SSPCON2,RCEN ; generate receive condition
incf i2cState,f ; update I2C state variable
return
; Read slave I2C [ I2C STATE -> 7 ]
ReadData
movfF SSPBUF,I2C_DATA_CHAR ; save off byte
dcfsnz read_max_count,f ; test if all done with reads
goto SendReadNack ; end of string so send NACK
MOVLW StringEndChar
CPFSEQ I2C_DATA_CHAR ; if equal then end of string
goto SendReadAck
SendReadNack ; Send Not Acknowledge
; movwf INDF ; save off null character
incf i2cState,f ; update I2C state variable
bsf SSPCON2,ACKDT ; acknowledge bit state to send (not ack)
bsf SSPCON2,ACKEN ; initiate acknowledge sequence
return
SendReadAck ; Send Acknowledge
MOVFF I2CEEADDR_TEMP, DATA_EE_ADDR
bcf SSPCON2,ACKDT ; acknowledge bit state to send
bsf SSPCON2,ACKEN ; initiate acknowledge sequence
CALL WriteEE
btfsc SSPCON2,ACKEN ; ack cycle complete?
goto $-2 ; no, so loop again
bsf SSPCON2,RCEN ; generate receive condition
return ;

; Generate I2C stop condition [ I2C STATE -> 8 ]
ReadStop
bcf PIE1,SSPIE ; disable SSP interrupt
bsf SSPCON2,PEN ; initiate I2C bus stop condition
clrf i2cState ; reset I2C state variable
; bsf sflag_event,rw_done ; set read/write done flag
return

I2C_ISR
; TEST FOR COMPLETION OF VALID I2C EVENT
btfss PIE1,SSPIE ; test is interrupt is enabled
goto test_buscoll ; no,
btfss PIR1,SSPIF ; test for SSP H/W flag
goto test_buscoll ; no,
bcf PIR1,SSPIF ; clear SSP H/W flag
call service_i2c ; service valid I2C event
GOTO I2C_END_ISR

; TEST FOR I2C BUS COLLISION EVENT
test_buscoll
btfss PIE2,BCLIE ; test if interrupt is enabled
goto I2C_END_ISR ; no,
btfss PIR2,BCLIF ; test if Bus Collision occured
goto I2C_END_ISR ; no,
bcf PIR2,BCLIF ; clear Bus Collision H/W flag
; call service_buscoll ; service bus collision error
I2C_END_ISR
RETURN

;----------------------------------------------------------------------
; *************** Bus Collision Service Routine ******************
;----------------------------------------------------------------------
service_buscoll
clrf i2cState ; reset I2C bus state variable
call init_vars ; re-initialize variables
return ;
;----------------------------------------------------------------------
; ************* Acknowledge Error Service Routine ***************
;----------------------------------------------------------------------
service_ackerror
; bcf eflag_event,ack_error ; reset acknowledge error event flag
clrf i2cState ; reset bus state variable
call init_vars ; re-initialize variables
return ;
 
Top