Bus Pirate and I2C EEPROM

This is a continuation of a series of posts on simple experiments I’m performing with my new Bus Pirate v4.0. Click to see me trying out the bus pirate v4.

I’ll connect up 3 EEPROM ICs on a breadboard and interface with them through the I2C bus. The particular ICs I will use are 24LC256 EEPROM chips each with a 256Kbit or 32KByte capacity.

The I2C bus is a two wire communication interface. One wire carries bidirectional data in a half duplex mode, that is data moves in only one direction at a time. It is named SDA. The other wire carries the clock signal. This signal provides the timing of data transfer on the bus. It is named SCK. The I2C bus has a simple messaging protocol consisting of START, STOP, and ACKnowledge signals. This allows a master on the bus (in our case that will be the Bus Pirate) to initiate and stop communications with any and all slave devices on the bus.

I2C Signals
I2C Signals

Each slave device has its own address. Three bits of the EEPROM ICs are set via three pins that are hardwired to set its address. This allows up to 8 of these EEPROM ICs to be connected on the same bus.
All the SDA and all the SCK pins on the EEPROM ICs are connected together and then wired to the corresponding data (MOSI) and clock (CLK) pins on the Bus Pirate. The address pins are connected to give each IC a different address. You will also need to wire up the Bus Pirate’s Vpu pin to 5V; this provides power for the pull-up resistors.

3x24LC256 circuit
3x24LC256 circuit

The 24LC256 chips provide a simple command interface for reading from and writing to the memory: Each chip has two (virtual) addresses: one for writing to the memory and one to read from the memory. To write to the memory, the master had to follow these steps:

  1. Issue an I2C START signal to indicate to slave devices that they should “listen” to the address that follows.
  2. Transmit the write address for the specific IC. The slave which recognized it’s own address will ACKnowledge.
  3. Transmit two bytes to give a starting memory address to the slave EEPROM.
  4. Transmit the bytes to write to the memory. Each byte needs to be ACK by the slave. The master need to only send the data bytes while the EEPROM memory address is automatically incremented.
  5. Issue an I2C STOP to indicate the end of the transaction.

Take note:

  • Each byte is followed by an ACK bit from the EEPROM IC if it accepts the data.
  • The master device always stays in control of the CLK signal, setting the place at which data is transmitted.

To read from the EEPROM the master needs to:

  1. Issue an I2C START signal.
  2. Optionally send the write address followed by the EEPROM memory address where reading should begin.
  3. Send the read address for the specific IC which will respond with an ACK.
  4. Clock out the data 8 bits at a time, acknowledging each received byte with an ACK bit.
  5. Issue an I2C STOP signal to end the transaction.

The Bus Pirate has a simple command interface over the serial connection.

Bus Pirate Commands
Bus Pirate Commands

First we need to select the correct communication mode and power up the bus:

  1. Enter m. We are presented with a list of modes to select from:
    1. HiZ
    2. 1-WIRE
    3. I2C
    4. SPI
    5. 2WIRE
    6. 3WIRE
    7. LCD
    8. DIO
    x. exit(without change)
    
    (1)>
  2. Enter 3 to select I2C mode. We are again presented with a selection:
    I2C mode:
     1. Software
     2. Hardware
    (1)>
  3. We might just as well use the hardware interface so 2 it is. We get presented with a speed selection:
    Set speed:
     1. 100KHz
     2. 400KHz
     3. 1MHz
    (1)>
    
  4. We press Enter to select the default value

The Bus Pirate gives us a new prompt indicating that we are now in I2C mode:

Ready
I2C>

We now need to power up the powersupply and activate the pull-up resistors.
The I2C bus needs pull-up resistors to keep the bus lines high. This allows the master and slaves to communicate by pulling the lines low.

  1. Enter W to power up the powersupply.
Power supplies ON

 

  • Enter P to switch on the pull-up resistors.
    Pull-up resistors ON

 

We are now ready to communicate with the EEPROM ICs. But how do know which addresses to use? We could read the datasheet for the 24LC256 to get the address or we could use a built in macro on the Bus Pirate that searches for addresses on the bus.

I2C>(0)
 0.Macro menu
 1.7bit address search
 2.I2C sniffer
I2C>(1)
Searching I2C address space. Found devices at:
0xA0(0x50 W) 0xA1(0x50 R) 0xA2(0x51 W) 0xA3(0x51 R) 0xA4(0x52 W) 0xA5(0x52 R)

We now have a list of all the addresses on the bus. Here we can see that for each IC there is a read and write address.
We now know which addresses to use. Let’s write something to the first EEPROM. The following commands will be written on one line to do the deed. Each command may be issued individually as well. The Bus Pirate allows that.

  1. [ will issue a START signal.
  2. 0xA0 writes the address to the bus.
  3. 0x00 0x00two bytes to tell the EEPROM from which memory address to start writing.
  4. 0xF0 A byte to be written to the EEPROM.
  5. “Hello” A string of characters to write into the EEPROM.
  6. 0x00 Another byte to be written to the EEPROM.
  7. ] will issue a STOP signal.

We end up with something like this:

I2C>[ 0xA0 0x00 0x00 0xF0 "Hello" 0x00 ]
I2C START BIT
WRITE: 0xA0 ACK
WRITE: 0x00 ACK
WRITE: 0x00 ACK
WRITE: 0xF0 ACK
WRITE: "H ACKe ACKl ACKl ACKo ACK"
WRITE: 0x00 ACK
I2C STOP BIT

Take note the ACK bit after the transmission of each byte.

Let’s try reading from the EEPROM this time:

  1. [ will issue a START signal.
  2. 0xA0 writes the address to the bus – we will be “writing” to the EEPROM in order to reset the memory counter/address back to zero
  3. 0x00 0x00two bytes to tell the EEPROM from which memory address to start reading
  4. [ Issue a START signal again
  5. 0xA1 is the read address of the first device
  6. rrrrrr will read 6 bytes from the bus

This is the result:

I2C>[ 0xa0 0x00 0x00 [ 0xa1 rrrrrrr ]
I2C START BIT
WRITE: 0xA0 ACK
WRITE: 0x00 ACK
WRITE: 0x00 ACK
I2C START BIT
WRITE: 0xA1 ACK
READ: 0xF0
READ:  ACK 0x48
READ:  ACK 0x65
READ:  ACK 0x6C
READ:  ACK 0x6C
READ:  ACK 0x6F
READ:  ACK 0x00
NACK
I2C STOP BIT

Note the string wrote out earlier was now read back as ASCII values. The Bus Pirate has an option to display the RAW value to the terminal. This is done using the o command:

I2C>o
 1. HEX
 2. DEC
 3. BIN
 4. RAW

(1)>4
Display format set

And we try again:

I2C>[ 0xa0 0x00 0x01 [ 0xa1 rrrrr ]
I2C START BIT
WRITE:   ACK
WRITE:   ACK
WRITE:   ACK
I2C START BIT
WRITE:   ACK
READ: 
READ:  ACK H
READ:  ACK e
READ:  ACK l
READ:  ACK l
READ:  ACK o
NACK
I2C STOP BIT

Links

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Leave a Comment