Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] i2c eeprom read problem using pic 16f877a

Status
Not open for further replies.

pratzz

Member level 5
Joined
Jun 15, 2012
Messages
83
Helped
6
Reputation
12
Reaction score
6
Trophy points
1,288
Activity points
1,781
Code:
list p=PIC16F877a
#include <p16F877a.inc>
errorlevel -302
__config _HS_OSC & _WDT_OFF & _LVP_OFF
;-------------------------------------------
; SPECIAL FUNCTION REGISTERS
;-------------------------------------------
;*******************Macro definitions*****************************
WRITE_ADDR  equ     b'10100000' ; Control byte for write operations
READ_ADDR   equ     b'10100001' ; Control byte for read operations
rs  equ 2
rw equ 3
en equ 4
;*******************Include file**********************************

;-------------------------------------------
; GENERAL PURPOSE REGISTERS
;-------------------------------------------
		CBLOCK 20h
count
count1
count3
count4
dat
disp
number
bytecount
temp
		ENDC


		ORG 0
		clrf STATUS
		movlw 00
		movwf PCLATH
		goto start
;-------------------------------------------
		org 04
		retfie
;----------------------------------------------

lcd_cmd
        movwf PORTD
        bcf PORTB,rs
        bcf PORTB,rw
        bsf PORTB,en
        call delay
        bcf PORTB,en
        retlw 00h
;------------------------------------------------------------------
lcd_data
        movwf PORTD
        bsf PORTB,rs
        bcf PORTB,rw
        bsf PORTB,en
        call delay
        bcf PORTB,en
        retlw 00h
;------------------------------------------------------------------
lcd_init
        movlw 38h
        call lcd_cmd
        call delay
        movlw 0eh
        call lcd_cmd
        call delay
        movlw 01h
        call lcd_cmd
        call delay
        movlw 06h
        call lcd_cmd
        call delay
        movlw 80h
        call lcd_cmd
        call delay
        call delay
         retlw 00h
;-------------------------------------------------------------------
delay
        movlw 02h
        movwf count3
here2   movlw 0ffh
        movwf count4
here    decfsz count4,1
        goto here
        decfsz count3,1
        goto here2
        retlw 00h
;-----------------------------------------------------------------


initialise
        clrf temp
        clrf count
		bcf STATUS,RP1
		bsf STATUS,RP0
        clrf TRISB
		clrf TRISD
		movlw b'00000111'
		movwf ADCON1
        movlw b'11111111'
        movwf   TRISC               ; Set PORTC to all inputs
        clrf    SSPSTAT             ; Disable SMBus inputs
        bsf     SSPSTAT,SMP         ; Disable slew rate control
        movlw   09h                ; Load 0x18 into WREG
        movwf   SSPADD              ; Setup 100 kHz I2C clock
        clrf    SSPCON2
		bcf     STATUS,RP0
        movlw   b'00101000'
        movwf   SSPCON              ; Enable SSP, select I2C Master mode
        bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
        bcf     PIR2,BCLIF
		retlw 00
;--------------------------------------------------------------
genstart

    bcf     STATUS,RP1
    bcf     STATUS,RP0          ; Select Bank 00
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,SEN         ; Generate Start condition
    bcf     STATUS,RP0          ; Select Bank 00
    start_wait
    btfss   PIR1,SSPIF          ; Check if operation completed
    goto    start_wait          ; If not, keep checking
    retlw   0
genstop
    bcf     STATUS,RP1
    bcf     STATUS,RP0          ; Select Bank 00
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,PEN         ; Generate Stop condition
    bcf     STATUS,RP0          ; Select Bank 00
stop_wait
    btfss   PIR1,SSPIF          ; Check if operation completed
    goto    stop_wait          ; If not, keep checking
    retlw   00
genrepstart
    bcf     STATUS,RP1
    bcf     STATUS,RP0          ; Select Bank 00
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,RSEN        ; Generate Restart condition
    bcf     STATUS,RP0          ; Select Bank 00
    repstart_wait
    btfss   PIR1,SSPIF          ; Check if operation completed
    goto    repstart_wait       ; If not, keep checking

    retlw   0
;-------------------------------------------------------------
receive
    bcf     STATUS,RP1
    bcf     STATUS,RP0          ; Select Bank 00
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,RCEN        ; Initiate reception of byte
    bcf     STATUS,RP0          ; Select Bank 00
rx_wait

    btfss   PIR1,SSPIF          ; Check if operation completed
    goto    rx_wait             ; If not, keep checking
    movf    SSPBUF,W           ; Copy byte to WREG
    ;movwf   dat                 ; Copy WREG to datai

    call lcd_data
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,ACKEN       ; Generate ACK/NO ACK bit
    bcf     STATUS,RP0          ; Select Bank 00
rx_wait2
    btfss   PIR1,SSPIF          ; Check if operation completed
    goto    rx_wait2            ; If not, keep checking
    movf    dat,w
    call lcd_data
    retlw   0
;-------------------------------------------------------------
transmit

    bcf     STATUS,RP1
    bcf     STATUS,RP0          ; Select Bank 00
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    movf    dat,W           ; Copy dat to WREG
    movwf   SSPBUF              ; Write byte out to device
  tx_wait
    btfss   PIR1,SSPIF          ; Check if operation completed
    goto    tx_wait             ; If not, keep checking
    bcf     PIR1,SSPIF

;-----------------------------------------------------------
    byteread
    call    genstart              ; Generate Start condition

                                       ; Send control byte
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   WRITE_ADDR          ; Load control byte for write
    movwf   dat                    ; Copy to datao for output
    call    transmit                 ; Send control byte to device

    ; Send word address high byte
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   12h               ; Load 0x5A for word address
    movwf   dat               ; Copy to datao for output
    call    transmit                 ; Send high byte to device

                                ; Send word address low byte
    call    genrepstart            ; Generate Restart condition

                                ; Send control byte
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   READ_ADDR           ; Load control byte for read
    movwf   dat                 ; Copy to datao for output
    call    transmit                 ; Send control byte to device
                               ; Read data byte
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,ACKDT       ; Select to send NO ACK bit
    bcf     STATUS,RP0
    call    receive              ; Read data byte from device
    call    genstop               ; Generate Stop condition

    retlw   0
    pageread
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   08h
    movwf   bytecount           ; Initialize counter to 16 bytes

    call    genstart              ; Generate start bit
                                ; Now send the control byte
                                ; for a write, to set address
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   WRITE_ADDR
    movwf   dat               ; Copy control byte to buffer
    call    transmit                 ; Output control byte to device

                                ; Send word address high byte
    bcf     STATUS,RP0          ; Select Bank 00
    movf    count,W                ; Use 0x5A for address to send
    movwf   dat                       ; Load 0x00 into datao
    call    transmit                  ; Send high byte to device

                                ; Send word address low byte
    bcf     STATUS,RP0          ; Select Bank 00
    call    genrepstart            ; Generate another start bit
                                ; to switch to read mode
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   READ_ADDR
    movwf   dat               ; Copy control byte to buffer
    call    transmit                 ; Output control byte to device

rxbyte
                                ; Finally, read the data byte
    bcf     STATUS,RP0          ; Select Bank 00
    decfsz  bytecount,F         ; Check if finished looping
    goto    continue            ; If not finished, keep going
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,ACKDT       ; Otherwise, select to send NO ACK bit
    call    receive                  ;   and input final byte from device

    call    genstop               ; Generate stop bit
    retlw   0

continue
    incf count,1
    ;incf count,1
    bsf     STATUS,RP0          ; Select Bank 01
    bcf     SSPCON2,ACKDT       ; Select to send ACK bit
    call    receive                  ; Input data from device
    goto    rxbyte              ; Continue looping
;-------------------------------------------
; Main program starts
;-------------------------------------------
start		call initialise
            call lcd_init

            call pageread
            call delay
            call delay
            call pageread
            movlw 0c0h
            call lcd_cmd
            call delay
            call delay
            call pageread
            call delay
            call delay
            call pageread

 x           goto x

   end
4 mhz crystal hs_osc it was ,i made that mistake and eeprom chip is 24c02 ,the sequential write is succesful but read is not
the lcd is just diplaying black screen instead of data i hav written into the eeprom
 
Last edited:

Hi,

In your earlier working code of you had Config XT_OSC, now you have HS_OSC ?

Have you changed crystal frequency ? - you should always put a comment in the code to say what frequency you are using, everything is dependant on it.

Also no mention of what eeprom chip you are using, its code and memory size.
 

4 mhz crystal hs_osc it was ,i made that mistake and eeprom chip is 24c02 ,the sequential write is succesful but read is not
 
Last edited:

Hi,

Seems when simulating it gets an IF signal the first time it enters this routine, but the second time it is just sitting there waiting for an IFsignal.

start_wait
btfss PIR1,SSPIF ; Check if operation completed
goto start_wait ; If not, keep checking
 
  • Like
Reactions: pratzz

    pratzz

    Points: 2
    Helpful Answer Positive Rating
even i m feelin sumthing like this is happenning but dont know why?
 
Last edited:

Hi,

This application note has some interesting info /diagrams.

Also the program code should help you, its in 18F assembler and using the MSSP module.
The code is virtually the same as 16F but basically less banking,think you will soon workout any minor differences.
**broken link removed**
 

Hi,

This application note has some interesting info /diagrams.

Also the program code should help you, its in 18F assembler and using the MSSP module.
The code is virtually the same as 16F but basically less banking,think you will soon workout any minor differences.
**broken link removed**
i have the application note for 16f and my sequential read and sequential write code just like the way they have told in their note ,although write is working but read is not working at all.

- - - Updated - - -

one of the problems was that i was not issuing return statement from transmit function.after correcting that something absurd is displaying
 

Hi,

i was not issuing return statement from transmit function

Yes that the 'fun' of coding !!

Added that return and the code runs to completion, but as you can see if I stop it when it receives the data W contains FF, not a valid lcd character.

Assume the app note is a reasonably recent one using mssp, some of Microchips early y 2000 code examples often did not work properly.
 

Attachments

  • ScreenShot001.jpg
    ScreenShot001.jpg
    49.3 KB · Views: 89

Code:
list p=PIC16F877a
#include <p16F877a.inc>
errorlevel -302
__config _HS_OSC & _WDT_OFF & _LVP_OFF
;-------------------------------------------
; SPECIAL FUNCTION REGISTERS
;-------------------------------------------
;*******************Macro definitions*****************************
WRITE_ADDR  equ     b'10100000' ; Control byte for write operations
READ_ADDR   equ     b'10100001' ; Control byte for read operations
rs  equ 2
rw equ 3
en equ 4
;*******************Include file**********************************

;-------------------------------------------
; GENERAL PURPOSE REGISTERS
;-------------------------------------------
		CBLOCK 20h
count
count3
count4
dat

bytecount
		ENDC


		ORG 0
		clrf STATUS
		movlw 00
		movwf PCLATH
		goto start
;-------------------------------------------
		org 04
		retfie

lcd_cmd
        movwf PORTD
        bcf PORTB,rs
        bcf PORTB,rw
        bsf PORTB,en
        call delay
        bcf PORTB,en
        retlw 00h
;------------------------------------------------------------------
lcd_data
        movwf PORTD
        bsf PORTB,rs
        bcf PORTB,rw
        bsf PORTB,en
        call delay
        bcf PORTB,en
        retlw 00h
;------------------------------------------------------------------
lcd_init
        movlw 38h
        call lcd_cmd
        call delay
        movlw 0eh
        call lcd_cmd
        call delay
        movlw 01h
        call lcd_cmd
        call delay
        movlw 80h
        call lcd_cmd
        call delay
        call delay
        retlw 00h
;-------------------------------------------------------------------
delay
        movlw 02h
        movwf count3
here2   movlw 0ffh
        movwf count4
here    decfsz count4,1
        goto here
        decfsz count3,1
        goto here2
        retlw 00h
;-----------------------------------------------------------------


initialise
        
        clrf count
		bcf STATUS,RP1
		bsf STATUS,RP0
        clrf TRISB
		clrf TRISD
		movlw b'00000111'
		movwf ADCON1
        movlw b'11111111'
        movwf   TRISC               ; Set PORTC to all inputs
        clrf    SSPSTAT             ; Disable SMBus inputs
        bsf     SSPSTAT,SMP         ; Disable slew rate control
        movlw   09h                ; Load 0x09 into WREG
        movwf   SSPADD              ; Setup 100 kHz I2C clock
        clrf    SSPCON2
		bcf     STATUS,RP0
        movlw   b'00101000'
        movwf   SSPCON              ; Enable SSP, select I2C Master mode
        bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
        bcf     PIR2,BCLIF
		retlw 00
;--------------------------------------------------------------
genstart

    bcf     STATUS,RP1
    bcf     STATUS,RP0          ; Select Bank 00
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,SEN         ; Generate Start condition
    bcf     STATUS,RP0          ; Select Bank 00
    start_wait
    btfss   PIR1,SSPIF          ; Check if operation completed
    goto    start_wait          ; If not, keep checking
    retlw   0
genstop
    bcf     STATUS,RP1
    bcf     STATUS,RP0          ; Select Bank 00
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,PEN         ; Generate Stop condition
    bcf     STATUS,RP0          ; Select Bank 00
stop_wait
    btfss   PIR1,SSPIF          ; Check if operation completed
    goto    stop_wait          ; If not, keep checking
    retlw   00
genrepstart
    bcf     STATUS,RP1
    bcf     STATUS,RP0          ; Select Bank 00
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,RSEN        ; Generate Restart condition
    bcf     STATUS,RP0          ; Select Bank 00
    repstart_wait
    btfss   PIR1,SSPIF          ; Check if operation completed
    goto    repstart_wait       ; If not, keep checking

    retlw   0
;-------------------------------------------------------------
receive
    bcf     STATUS,RP1
    bcf     STATUS,RP0          ; Select Bank 00

    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,RCEN        ; Initiate reception of byte
    bcf     STATUS,RP0          ; Select Bank 00
rx_wait

    btfss   PIR1,SSPIF          ; Check if operation completed
    goto    rx_wait
    movf    SSPBUF,W           ; Copy byte to WREG
    call lcd_data
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,ACKEN       ; Generate ACK/NO ACK bit
    bcf     STATUS,RP0          ; Select Bank 00
rx_wait2
    btfss   PIR1,SSPIF          ; Check if operation completed
    goto    rx_wait2            ; If not, keep checking
    retlw   0
;-------------------------------------------------------------
transmit

    bcf     STATUS,RP1
    bcf     STATUS,RP0          ; Select Bank 00
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    movf    dat,W               ; Copy dat to WREG
    movwf   SSPBUF              ; Write byte out to device
  tx_wait
    btfss   PIR1,SSPIF          ; Check if operation completed
    goto    tx_wait             ; If not, keep checking
    bcf     PIR1,SSPIF
    retlw 00h
;-----------------------------------------------------------
    


    pageread
    bcf     STATUS,RP1
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   08h
    movwf   bytecount           ; Initialize counter to 8 bytes

    call    genstart              ; Generate start bit
                                ; Now send the control byte
                                ; for a write, to set address
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   WRITE_ADDR
    movwf   dat               ; Copy control byte to buffer
    call    transmit                 ; Output control byte to device

                                ; Send word address high byte
    bcf     STATUS,RP0          ; Select Bank 00
    movf    count,W                ; for address to send
    movwf   dat                       ; Load 0x00 into dat
    call    transmit                  


    bcf     STATUS,RP0
    call    genrepstart            ; Generate another start bit

                               ; to switch to read mode
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   READ_ADDR
    movwf   dat               ; Copy control byte to buffer
    call    transmit                 ; Output control byte to device
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,ACKDT   
rxbyte
                              ; Finally, read the data byte
    bcf     STATUS,RP0          ; Select Bank 00
    decfsz  bytecount,F         ; Check if finished looping
    goto    continue            ; If not finished, keep going
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,ACKDT       ; Otherwise, select to send NO ACK bit
    call    receive                  ;   and input final byte from device
    call    genstop               ; Generate stop bit
    retlw   0

continue
  
    bsf     STATUS,RP0          ; Select Bank 01
    bcf     SSPCON2,ACKDT       ; Select to send ACK bit
    call    receive                  ; Input data from device
    goto    rxbyte              ; Continue looping
;-------------------------------------------
; Main program starts
;-------------------------------------------
start		call initialise
            call lcd_init

          
            call pageread
            call delay
            call delay
            movlw 08h
            addwf count
            call pageread
            call delay
            call delay
            movlw 0c0h
            call lcd_cmd
            movlw 08h
            addwf count
            call pageread
            call delay
            call delay
            movlw 08h
            addwf count
            call pageread

 x           goto x

   end

my program is working now but instead of reading bytes 0-7,8-15,16-23,24-31
it is reading 0-7,7-14,14-21,21-28
 

Hi,

Seems you have changed the lcd code, it does not display at all now.
 

on hardware it is working now but not on simulation ,the error is most probably of delay thats why this is happening. i will check that on monday as my ic got damaged while re burning the program.
 

on hardware it is working now but not on simulation ,the error is most probably of delay thats why this is happening. i will check that on monday as my ic got damaged while re burning the program.


Hi,

Looking at your code posted in last entry I cannot see where you are writing to the Eeprom ? - Your start routine is just pagereads ?
Assume you have another program to just write out ?

What app note have you used ?

Have had time to use app note 989, linked in post #6, to program up the 24lc08 chip on my diy dev board.

It works fine and if you follow its code example though it clearly shows the sequence of Control, Address and Data.
Most instructions should be very similar to the 877A, less the banking.
Always find using Banksel on the 16F chip so much easier than the BSFs as its so easy to get them the wrong way round.

Seems your i2c buad rate of 0x09 is correct for ic2 at 100k using a 4 meg xtal.
What about the SCK and SDA pull up resistors, what value are you using?

Do you have a PK2 programmer or one that can read /write to the eeprom - its handy for seeing whats actually in there and writing some values in there to check your I2C Read routines

Did try to Sim the code that works on the hardware but no success though I am not expert with that despite its Instrument I2C Debugger.
 

Hi,

Looking at your code posted in last entry I cannot see where you are writing to the Eeprom ? - Your start routine is just pagereads ?
Assume you have another program to just write out ?

What app note have you used ?

Have had time to use app note 989, linked in post #6, to program up the 24lc08 chip on my diy dev board.

It works fine and if you follow its code example though it clearly shows the sequence of Control, Address and Data.
Most instructions should be very similar to the 877A, less the banking.
Always find using Banksel on the 16F chip so much easier than the BSFs as its so easy to get them the wrong way round.

Seems your i2c buad rate of 0x09 is correct for ic2 at 100k using a 4 meg xtal.
What about the SCK and SDA pull up resistors, what value are you using?

Do you have a PK2 programmer or one that can read /write to the eeprom - its handy for seeing whats actually in there and writing some values in there to check your I2C Read routines

Did try to Sim the code that works on the hardware but no success though I am not expert with that despite its Instrument I2C Debugger.
i hav used application note 976a with some modifications.and yes i have separate program for write operation.i hav winpro programmer which enable me to read tha data i have written.
and your are right about my baud rate and i have used 10k pull ups.
 

Hi,

It sounds like your hardware is fine, think you must have some bug in your code.

This is what works for my page read, virtually the same apart from the banking.

To obvious difference with yours is that it sends out the full 16 bit address, you only send out the high byte, so expect the low byte could be anything ?

If your programmer can read the eeprom does your Write routine put the data into the chip correctly ?

Perhaps post your write routine, I have a 877a somewhere and can test it later today

Code:
SequentialRead
    movlw   NUMBYTES			; = dec  16
    movwf   bytecount           ; Initialize counter to NUMBYTES

    call   BSTART              ; Generate start bit
                                ; Now send the control byte
                                ; for a write, to set address
    movlw   WRITE_ADDR
    movwf   datao               ; Copy control byte to buffer
    call   TX_BYTE             ; Output control byte to device

                                [U]; Send word address high byte[/U]
    movlw   [U]0x5A [/U]               ; Load 0x5A for word address
    movwf   datao               ; Copy to datao for output
    call   TX_BYTE             ; Send high byte to device

                                ; [U]Send word address low byte[/U]
    movlw   [U]0x00[/U]               ; Load 0x5A for word address
    movwf   datao               ; Copy to datao for output
    call   TX_BYTE             ; Send word address to device

    call   BRESTART            ; Generate another start bit
                                ;   to switch to read mode
    movlw   READ_ADDR
    movwf   datao               ; Copy control byte to buffer
    call   TX_BYTE             ; Output control byte to device

rxbyte
                                ; Finally, read the data byte
    decfsz  bytecount,F         ; Check if finished looping
    bra     continue            ; If not finished, keep going
    bsf     SSP1CON2,ACKDT       ; Otherwise, select to send NO ACK bit
    call    RX_BYTE             ;   and input final byte from device
	return
    call   BSTOP               ; Generate stop bit
    return

continue
    bcf     SSP1CON2,ACKDT       ; Select to send ACK bit
    call   RX_BYTE             ; Input data from device

    movff   datai,B16			; display data , 1 byte at a time
   	call	row2_display
    call    delay1sec

    bra     rxbyte              ; Continue looping
 

actually 24c02 has 8 bit address only and yes my programmer is showing data written properly
 

Try putting 10ms delay between reading and writing cycle for i2c.
 

ya delay was the problem.

- - - Updated - - -

ya delay was the problem.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top