cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F334 with 24C32 EEPROM I2C Read/Write

Manu Abraham
Senior
Posted on February 22, 2017 at 09:59

Hi,

Trying to get I2C communication between a F334 and a 24C32 EEPROM working,

The read and write functions do return correctly, but the reads do not match what

has been written to the EEPROM. Struggling to find the issue at hand and in the

thought that someone could possibly lend me a hand on this issue, which would

be very helpful. The EEPROM's address lines are all grounded, which effectively

puts the EEPROM at an address of 0xA0

The output I am reading in a terminal, which says:

-------------= I2C1 REG dump =-------------

I2C_CR1 : 0x01

I2C_CR2 : 0x20404a1

I2C_OAR1 : 0x8000

I2C_OAR2 : 0x00

I2C_TIMINGR : 0x10c08dcf

I2C_TIMEOUTR: 0x00

I2C_ISR : 0x01

I2C_ICR : 0x00

I2C_PECR : 0x00

I2C_RXDR : 0xff

I2C_TXDR : 0x00

-------------------------------------------

Data: ff ff ff ff

-------------= I2C1 REG dump =-------------

I2C_CR1 : 0x01

I2C_CR2 : 0x20404a1

I2C_OAR1 : 0x8000

I2C_OAR2 : 0x00

I2C_TIMINGR : 0x10c08dcf

I2C_TIMEOUTR: 0x00

I2C_ISR : 0x01

I2C_ICR : 0x00

I2C_PECR : 0x00

I2C_RXDR : 0xff

I2C_TXDR : 0x00

-------------------------------------------

Data: ff ff ff ff

which doesnt reflect what I have written. I was expecting 0x00, 0x01, 0x02, 0x03

as expected as in:

i2c_wr(0xa0, 0x00, 0x00);

i2c_wr(0xa0, 0x01, 0x01);

i2c_wr(0xa0, 0x02, 0x02);

i2c_wr(0xa0, 0x03, 0x03);

instead of 0xff, 0xff, 0xff, 0xff.

Any thoughts/suggestions ?

Thanks.

#stm32f334-i2c

Note: this post was migrated and contained many threaded conversations, some content may be missing.
26 REPLIES 26
AvaTar
Lead
Posted on February 22, 2017 at 10:06

Are you sure you addressing the slave correctly ?

You should see an Acknowledge at bit 9. You have a scope or logic analyzer ?

All read bytes 0xFF looks suspiciously like the slave(s) not responding at all.

I2C has pull-ups, so dead reads return 0xFF.

AvaTar
Lead
Posted on February 22, 2017 at 11:07

Looks o.k. to me. I would interpret that as ACK, too.

Coincidentally, erased Flash/EEPROM cells also contain 0xFF, so the read bytes might reflect reality.

Perhaps you need to concentrate on the validation of you programming process (as described in the datasheet).

S.Ma
Principal
Posted on February 22, 2017 at 11:14

To me it looks like the eeprom datasheet was not read entirely. When a data is written in eeprom (any) you need to wait for the eeprom erase and write operation which would take up to 10msec. During this time, the eeprom is busy and will reject (NACK) your request. If Nack, noone set the read operation and the pull-up on the bus will tell 0xFF...

Ronald Niederhagen
Associate II
Posted on February 22, 2017 at 11:53

I'm using a 24C08 which should be similar, just smaller.

Have you checked if pin 7 (which is WP, write_protect) is low? At least during the write.

I'm using mbed, so my code looks different, but I guess you can figure it out from there:

void byte_write(int dev_addr,int w_addr,uint8_t d)

{

    char cmd[2];

    cmd[0] = w_addr & 0xFF;

    dev_addr = ((w_addr & 0x300) >> 7) | (dev_addr & 0xF0);

    cmd[1] = d;

    i2c_bus.write(dev_addr,cmd,2);

    wait_ms(10); // wait until write cycle is complete

}

uint8_t byte_read(int dev_addr,int w_addr)

{

    char cmd[2];

    cmd[0] = w_addr & 0xFF;

    dev_addr = ((w_addr & 0x300) >> 7) | (dev_addr & 0xF0);

    i2c_bus.write(dev_addr,&cmd[0],1,true); // it is important to make this a 'repeated' access

    i2c_bus.read(dev_addr,&cmd[1],1);

    return(cmd[1]);

}

Not pretty, but it works for me.

Posted on February 22, 2017 at 10:54

The address should be correct, I guess.

A0, A1, A2 pins connected to ground, which puts the EEPROM at 0xA0

The pins are pulled up 3k9 resistors. Yes, I agree that the FF's are bogus reads.

I am not really sure whether the slave is not responding at all. It appears to respond,

looking at the attached waveform ?

The bottom 2 traces are a zoomed version of the 2 upper traces.

________________

Attachments :

20170222_145436.jpg : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HytQ&d=%2Fa%2F0X0000000bDb%2FHl1.hGj58ibyhbPBJz31iKZuHdMNY1oVOMjEhKz1L0M&asPdf=false
Posted on February 22, 2017 at 14:04

The EEPROM datasheet.

http://www.atmel.com/images/doc0336.pdf

Looking at Page11 Fig 2, Byte Write. It says

Start

Slave Address+R/W -> ACK

Reg Address MSB -> ACK

Reg Address LSB ->ACK

Data ->ACK

Stop

The problem that I perceive, sending only the Reg MSB;

while (I2C_GetFlagStatus(I2C1, I2C_ISR_TXIS) == RESET) {};

//Send the address of the register we wish to write to

I2C_SendData(I2C1, (uint8_t)reg); // msb

Modifying the code to send the LSB too as described in the datasheet..

but, when I try to do send in the LSB, checking for the next 

I2C_ISR_TXIS

to send the LSB, the TXIS flag is not raised and the loop goes on indefinitely.

Having lost state completely, Am I looking at things incorrectly ?

Posted on February 22, 2017 at 14:07

I tried modifying the code to have more than 10ms delay after the write for the read,

but that made no difference at all. changes look thus:

i2c1_init();

led_init();

led_toggle();

i2c_wr(0xa0, 0x00, 0xde);

i2c_wr(0xa0, 0x01, 0xad);

i2c_wr(0xa0, 0x02, 0xbe);

i2c_wr(0xa0, 0x03, 0xef);

delay(10);

/* Infinite loop */

while (1) {

debug_i2c1();

delay(10);

i2c_rd(0xa1, 0x00, dbuf, 4);

sprintf((char *)strbuf, 'Data: %02x %02x %02x %02x\r\n',

dbuf[0], dbuf[1], dbuf[2], dbuf[3]);

putstr(USART1, strbuf);

led_toggle();

}

-------------= I2C1 REG dump =-------------

I2C_CR1 : 0x01

I2C_CR2 : 0x20404a1

I2C_OAR1 : 0x8000

I2C_OAR2 : 0x00

I2C_TIMINGR : 0x10c08dcf

I2C_TIMEOUTR: 0x00

I2C_ISR : 0x01

I2C_ICR : 0x00

I2C_PECR : 0x00

I2C_RXDR : 0xff

I2C_TXDR : 0x00

-------------------------------------------

Data: ff ff ff ff

Maybe I am missing something completely.
Posted on February 22, 2017 at 14:11

Sigh, tried the delay with no perceivable difference in the result.

Maybe something is really odd in my setup.

Posted on February 22, 2017 at 14:12

...

    i2c_bus.write(dev_addr,cmd,2);

    wait_ms(10); // wait until write cycle is complete

...

Not pretty, but it works for me.

Too lazy to look up the datasheet at the moment, but AFAIK, there is a status register with a BUSY flag, to check that an erase/write has finished.

Edit: Checked actually, and has none. The datasheet suggests Acknowledge Polling instead.