chwill210
Posts: 4
Joined: Tue Feb 16, 2016 12:41 pm

Problem writing to 24LC256 using i2c and SMBUS

Sun Feb 21, 2016 5:04 pm

Hi All. I cannot get my Pi2 to write to a 24LC256 EEPROM with SMBUS. I am a novice to the Pi and to i2c communication. So operator error is highly suspected!

I believe the EEPROM is working fine. I can read/write to it flawlessly using a PICAxe chip. I am pretty sure I have the Pi set up correctly as I can read from the EEPROM using the following Python code:

Code: Select all

import smbus
address = 0x50             # 24LC256 i2c bus address

i2cmsbyte = 0
i2clsbyte = 24		# Reads starting from EEPROM register 24

bus.write_byte(address,i2cmsbyte)
bus.write_byte(address,i2clsbyte)
eevalue1 = bus.read_byte(address)
eevalue2 = bus.read_byte(address)
eevalue = (eevalue2<<8) + eevalue1
print (eevalue)
As I understand, to read or write to this part, you must first write the target register/address (word), most significant byte first. The first write command must also include the I2C read/write bit (read = 1, write = 0). The 0x50 address does not include the read bit (as far as I understand), but the code works correctly. When I change "address" to 0xA1, the code bombs.

I have tried using 0xA1 for writing the most significant address byte and 0x50 for the least significant byte and that bombs too. This is part of my confusion. In any case, the above code reads the value stored at register 24 perfectly.

To write, I started with the following:

Code: Select all

import smbus
address1 = 0xA0         # i2c bus address 0x50 and write bit = 0
address2 = 0x50         # i2c bus address only

i2cmsbyte = 0
i2clsbyte = 24		# Writes to EEPROM address 24

eevaluemsbyte = 1
eevaluelsbyte = 4	        # word value = 260
    
bus.write_byte(address1,i2cmsbyte)
bus.write_byte(address2,i2clsbyte)
bus.write_byte(address2,eevaluelsbyte)
bus.write_byte(address2,eevaluemsbyte)
This code bombs at the first bus.write command. If I substitute 0x50 for address1, the code executes without error, but the 24LC256 won't accept the value (as expected - no write bit).

I have tried different SMBUS commands and have played with the addresses. Nothing works. I suspect that SMBUS won't accept an 8-bit i2c device address (0x50 doesn't bomb, 0xA1 bombs). If I'm right, how do I transmit the read/write bit?

I am about to punt! Any help would be greatly appreciated.

User avatar
joan
Posts: 14935
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Problem writing to 24LC256 using i2c and SMBUS

Sun Feb 21, 2016 8:03 pm

Use 0x50. The I2C driver does the rest.

User avatar
joan
Posts: 14935
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Problem writing to 24LC256 using i2c and SMBUS

Mon Feb 22, 2016 8:43 am

I spilt tea on my keyboard and it was a rush to even type that much before the keyboard auto delete function took over.

I2C addresses are 7-bit in length (actually 7 or 10, but never 8). Your device is at address 0x50. When the I2C driver places the address on the bus is shifts it up one place to the top of the control byte and uses the least significant bit as the read/write flag (as per the I2C specification).

So if you examine bus traffic you will see 0xA1 for a read and 0xA0 for a write. People mistakenly think that 0xA1 is the read address and 0xA0 is the write address.

chwill210
Posts: 4
Joined: Tue Feb 16, 2016 12:41 pm

Re: Problem writing to 24LC256 using i2c and SMBUS

Tue Feb 23, 2016 2:25 am

Thanks for the quick reply Joan!

So I tried the following code:

Code: Select all

import smbus
address2 = 0x50         # i2c bus address only

i2cmsbyte = 0
i2clsbyte = 24               # Writes to EEPROM address 24

eevaluemsbyte = 1
eevaluelsbyte = 4         # word value = 260
       
bus.write_byte(address,i2cmsbyte)
bus.write_byte(address,i2clsbyte)
bus.write_byte(address,eevaluelsbyte)
bus.write_byte(address,eevaluemsbyte)
This code does not create an error, but the value is not written. As I understand the 24LC256, both its read and write actions are initiated by writing the target register word address msbyte followed by the lsbyte in a second step. The difference is in the read/write bit of the first i2c address byte. So if I use the 7-bit i2c address 0x50 with the bus.write_byte command, both read and write commands look identical to the EEPROM. I think with the first "read" sequence "bus.write_byte(0x50,i2cmsbyte)," SMBUS is doing exactly what you said - transmitting 0xA1. The EEPROM executes a read correctly.

But when I want to write, the first write sequence "bus.write_byte(0x50,i2cmsbyte)," is doing the same thing - transmitting 0xA1. According to the 24LC256 datasheet, this first write should transmit 0xA0

I tried cheating by substituting "bus.read_byte_data(address,i2cmsbyte)" for the first command. The thought was that it would invert the read/write bit, but that didn't work either.

Any other ideas?

User avatar
joan
Posts: 14935
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Problem writing to 24LC256 using i2c and SMBUS

Tue Feb 23, 2016 8:25 am

Each SMBus call will be a separate transaction with start (S) and stop (P) conditions. I expect you need to send multiple byte commands, not single byte commands.

e.g.

S Addr Wr [A] byte1 [A] byte2 [A] ... [A] byten [A] P

rather than

S Addr Wr [A] byte1 [A] P
S Addr Wr [A] byte2 [A] P
S Addr Wr [A] byte3 [A] P

The datasheet for your device should show the needed transaction in terms similar to those I use above.

If you can identify the needed transaction it shouldn't be too hard to convert it into SMBus commands.

chwill210
Posts: 4
Joined: Tue Feb 16, 2016 12:41 pm

Re: Problem writing to 24LC256 using i2c and SMBUS

Wed Feb 24, 2016 2:07 am

From Microchip's datasheet, the required 24LC256 transaction is straightforward (as best I can tell):

S i2caddress Wr [A] regmsbyte [A] reglsbyte [A] datalsbyte [A] datamsbyte [A] P

I tried the following block:

Code: Select all

address = 0x50
    writestring = [regmsbyte, reglsbyte, datalsbyte, datamsbyte]
    regmode = 0x00
    bus.write_i2c_block_data(address,regmode,writestring)
This did not generate an error, but did not write the value. I tried changing regmode to 0x01 for grins with same result.

You are right, this should be simple. But it hasn't been so far. I have tried every SMBUS command six ways each with no luck. I'm hoping someone out there has done this successfully.

fsr
Posts: 88
Joined: Wed Jan 13, 2016 2:29 am

Re: Problem writing to 24LC256 using i2c and SMBUS

Wed Feb 24, 2016 2:34 am

You've tried using 16bit values with i2c_smbus_write_word_data() ?
https://github.com/raspberrypi/linux/bl ... s-protocol

User avatar
joan
Posts: 14935
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Problem writing to 24LC256 using i2c and SMBUS

Wed Feb 24, 2016 2:48 am

chwill210 wrote:From Microchip's datasheet, the required 24LC256 transaction is straightforward (as best I can tell):

S i2caddress Wr [A] regmsbyte [A] reglsbyte [A] datalsbyte [A] datamsbyte [A] P

I tried the following block:

Code: Select all

address = 0x50
    writestring = [regmsbyte, reglsbyte, datalsbyte, datamsbyte]
    regmode = 0x00
    bus.write_i2c_block_data(address,regmode,writestring)
This did not generate an error, but did not write the value. I tried changing regmode to 0x01 for grins with same result.

You are right, this should be simple. But it hasn't been so far. I have tried every SMBUS command six ways each with no luck. I'm hoping someone out there has done this successfully.
Try

Code: Select all

address = 0x50
    writestring = [reglsbyte, datalsbyte, datamsbyte]
    regmode = regmsbyte
    bus.write_i2c_block_data(address,regmode,writestring)
(see http://abyz.co.uk/rpi/pigpio/python.htm ... block_data for what I think that command should send).

chwill210
Posts: 4
Joined: Tue Feb 16, 2016 12:41 pm

Re: Problem writing to 24LC256 using i2c and SMBUS

Fri Feb 26, 2016 12:36 am

Thanks Joan! This code did the trick.

I found a slight issue with the read code I posted originally, so this is the final python code I am using to read and write word data to my 24LC256 EEPROM:

Code: Select all

import smbus
address = 0x50     # 24LC256 i2c address - no address pins connected
regmsbyte = x     #most significant byte of target 24LC256 register word address
reglsbyte = y     #least significant byte of target 24LC256 register word address

# Read word using the 24LC256's Random Read operation
bus.write_byte_data(address,regmsbyte,reglsbyte)     #24LC256 writes to the Address Pointer
datalsbyte = bus.read_byte(address)     #24LC256 responds w/data & increments Pointer by 1
datamsbyte = bus.read_byte(address)     #24LC256 responds w/data (& increments Pointer by 1)

# Write word using the 24LC256's Byte Write operation
datalsbyte = a
datamsbyte = b
writestring = [reglsbyte, datalsbyte, datamsbyte]
bus.write_i2c_block_data(address,regmsbyte,writestring)

# writestring may contain up to 32 bytes (31 data bytes)     
I am reading and writing least significant byte first because the PICaxe processor I am sharing
the EEPROM with writes and reads LS byte first.

Thanks again for your help! Cheers

Return to “Troubleshooting”