I2C-24LC256 intermittent read error

General discussion relating to the library modules supplied with the compiler

Moderators: David Barker, Jerry Messina

Post Reply
Gunplumber
Posts: 38
Joined: Wed Nov 02, 2022 10:31 am

I2C-24LC256 intermittent read error

Post by Gunplumber » Sun Sep 10, 2023 4:46 am

Hi guys
I am using the following code to read a block of data (256 bytes) from an external eeprom 24LC256. PIC is a 26K40.
The below code works on the first power up of the device and first run through the sub, but on subsequent reads, it sometimes locks up somewhere between the Start and stop commands.
Whats frustrating is that it only does it on average 1 time in 3 or 4 attempts.
I have made sure that the Variable "XBUS_model" is always within bounds (0-30) that result in readable addresses from the Eeprom.
Any ideas as to why this might be happening?

I have noticed some examples of code with "I2C.Acknowledge(I2C_NOT_ACKNOWLEDGE)" instead of what i have "I2C.Acknowledge(I2C_ACKNOWLEDGE)" but i could not get it to work at all with "I2C_NOT_ACKNOWLEDGE"
I have also noticed that if i pre-program my entire eeprom (bench programmer) with $00 instead of $FF then it always locks up with the below code.
As soon as i re-program it with $FF it will complete the read cycle again.
This is across 3 separate boards, two with surface mount eeproms and one with socketed DIP so it's defiantly not a faulty chip.

Cheers
Lee

Code: Select all

 Sub EXT_EEPROM_READ()
   TimerEnabled = false         //turn off timer interrupts
   
   Model_number_offset= XBUS_Model*256 
        Address=Model_number_offset     //+Address_counter 
        I2C.Start
        I2C.WriteByte(Eprom_cmd)
        I2C.WriteByte(Address.Byte1)        
        I2C.WriteByte(Address.Byte0)        
        I2C.Restart                     //set address for first read.     
        I2C.WriteByte(Eprom_cmd + 1)
        For Page_counter =0 To 255 //63
            Model_system_data(Page_counter)= I2C.ReadByte
            I2C.Acknowledge(I2C_ACKNOWLEDGE)            
        Next
        I2C.Stop
     TimerEnabled = True        //turn timer interrupts back on
End Sub 


Gunplumber
Posts: 38
Joined: Wed Nov 02, 2022 10:31 am

Re: I2C-24LC256 intermittent read error

Post by Gunplumber » Sun Sep 10, 2023 7:25 am

Hi Guys
Disregard the above post.. I think i have it sorted.. I re-read the 24LC256 data sheet again and finally the below excerpt sunk in!. :roll:
Sequential reads are initiated in the same way as a
random read except that after the 24XX256 transmits
the first data byte, the master issues an acknowledge
as opposed to the Stop condition used in a random
read. This acknowledge directs the 24XX256 to
transmit the next sequentially addressed 8-bit word
(Figure 8-3). Following the final byte transmitted to the
master, the master will NOT generate an acknowledge,
but will generate a Stop condition.
To provide sequen-
tial reads, the 24XX256 contains an internal Address
Pointer which is incremented by one at the completion
of each operation.



So i have amended my code as follows, which so far now works perfectly..

Code: Select all

 Sub EXT_EEPROM_READ()
   TimerEnabled = false         //turn off timer interrupts
   
   Model_number_offset= XBUS_Model*256 
        Address=Model_number_offset     //+Address_counter 
        I2C.Start
        I2C.WriteByte(Eprom_cmd)
        I2C.WriteByte(Address.Byte1)        
        I2C.WriteByte(Address.Byte0)        
        I2C.Restart                     //set address for first read.     
        I2C.WriteByte(Eprom_cmd + 1)
        For Page_counter =0 To 255 //63
            Model_system_data(Page_counter)= I2C.ReadByte
            If Page_counter=255 Then
                I2C.Acknowledge(I2C_NOT_ACKNOWLEDGE)            
            Else
                I2C.Acknowledge(I2C_ACKNOWLEDGE) 
            End If
        Next
        I2C.Stop
     TimerEnabled = True        //turn timer interrupts back on
End Sub

Cheers
Lee

Jerry Messina
Swordfish Developer
Posts: 1488
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: I2C-24LC256 intermittent read error

Post by Jerry Messina » Sun Sep 10, 2023 12:15 pm

Another way to do that using the overloaded ReadByte(pAck as bit) routine is to loop reading all but the last byte, and then handle the last byte outside the loop...

Code: Select all

// loop reading all but the last byte
For Page_counter = 0 To 254
    Model_system_data(Page_counter) = I2C.ReadByte(I2C_ACKNOWLEDGE)
Next
// read last byte with NACK
Model_system_data(255) = I2C.ReadByte(I2C_NOT_ACKNOWLEDGE)
I2C.Stop

Post Reply