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
S.Ma
Principal
Posted on February 22, 2017 at 15:50

Add 10msec delay between each write. Programming start after the stop bit.

Or try 

https://community.st.com/0D50X00009XkW1qSAF

 
Posted on February 22, 2017 at 15:09

Agreed, looking at the BUSY flag is the better way to do it. But as I said, it's not pretty and the 10ms are OK according to the data sheet. And I'm trying to highlight the principle here, not good coding style.

However, one thing I'd like to point out: the i2c transactions usually start with a START condition (D making a 1->0 transition while CLK is 1) and ends with a STOP condition. Sometimes this STOP condition must be replaced by a 'repeated start condition'. For instance when reading:

.....

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);

....

Notice the 4th parameter to write tells the interface logic to do exactly the above.

And the 24C08 is very picky about this. The write with the usual STOP condition will cause the code not to work.

Posted on February 22, 2017 at 15:21

Agreed, looking at the BUSY flag is the better way to do it. But as I said, it's not pretty and the 10ms are OK according to the data sheet. And I'm trying to highlight the principle here, not good coding style.

My comment was less about coding style, but more about the method.

But as it turned out, there is no BUSY flag to check. The datasheet suggests ACK polling, i.e. trying cyclical writes until one gets a positive ACK.

I'm quite sure some serial Flash/Eeprom chips (MCP ?) do have such flags.

Notice the 4th parameter to write tells the interface logic to do exactly the above.

And the 24C08 is very picky about this. The write with the usual STOP condition will cause the code not to work.

That's correct. This chips obviously need it to advance their internal state machine.

That is the disadvantage of running a 'stateful' device via such an ancient bus.

BTW, when using a fixed delay, I would check with the datasheet. Erase/program times rise sharply with temperature, and less pronounced with age (wear).

Posted on February 22, 2017 at 15:44

You are right: the I2C transactions usually have a ACK bit at the end. And polling that would be the right way to do it.

I was trying to explain the principle of concatenating transactions and didn't want to get that lost in a waterproof handshake between the EEPROM and the controller (dealing with timeout, interrupts, specs, etc.).

Back to Manu's original point:

  • have you tried to read with concatenating the transactions?
  • you might also look at the datasheet and see how the LOW and the HIGH byte of the address wants to be transferred.

The 24C08 expects the higher bits of the memory address in the lower bits of the device address. Look at my code snippet above. Don't know how the 24C32 deals with this.

Posted on February 23, 2017 at 15:02

The delay seems necessary only at the end of the entire write transaction.

A delay after each byte being written seems unnecessary.

Witha concatenated write, that getsvery clear; in the attachment.

6mS seems to be the absolute minimum delay required there.

Trying to avoid that 6mS blind delay in there, trying to look for the ACK

instead, as was being discussed. But cant seem how to go ahead looking

for the ACK instead.

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

I2C_CR1 : 0x01

I2C_CR2 : 0x22004a1

I2C_OAR1 : 0x8000

I2C_OAR2 : 0x00

I2C_TIMINGR : 0x10c08dcf

I2C_TIMEOUTR: 0x00

I2C_ISR : 0x21

I2C_ICR : 0x00

I2C_PECR : 0x00

I2C_RXDR : 0xef

I2C_TXDR : 0x00

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

Byte0: 0x0f

0f0e 0d0c 0b0a 0908

0706 0504 0302 0100

dead beef dead beef

dead beef dead beef

________________

Attachments :

write_bytes.c.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HysN&d=%2Fa%2F0X0000000bDT%2FkwE9icUK97iVfkXbiKCJ6dv8nbTJgN_EweB4fwGN.eI&asPdf=false
Posted on February 24, 2017 at 09:00

The ACK value might be the return value of the transaction function. Take a look at the documentation of the read and write functions.

You might need to disable interrupts to guarantee the sequence of events executes as intended. That depends on what your code is doing.

Posted on February 28, 2017 at 13:04

After not finding the mysterious bird:

I am wondering what would be the order of the ISR flags:

It appears to me that the ACK bit occurs after 9 clocks, after which the TXIS flag is set.

When you are checking for the TXIS flag already, why should one check for the ACK flag ?

It could be helpful, if either of you could explain.

This is what the datasheet states:

Page: 878

Transmission

If the I2C_TXDR register is not empty (TXE=0), its content is copied into the shift register

after the 9th SCL pulse (the Acknowledge pulse). Then the shift register content is shifted

out on SDA line.

Page: 893

Master transmitter

In the case of a write transfer, the TXIS flag is set after each byte transmission, after the 9th

SCL pulse when an ACK is received.

Posted on January 19, 2018 at 12:46

Hi Ronald,

I am trying to make 24c08 work with STM32F030R8. I have using HAL_I2C_Mem_Write and 

HAL_I2C_Mem_Read functions. It is working till address is 0xFF. If i write on address 0x100 it gives me garbage value. The device address is 0xA0.

Any idea where am i going wrong ?

Posted on January 19, 2018 at 12:53

Hi,

Are you sure you are using 16Bit addres size with HAL_I2C_Mem_Write and Read functions?

Regards

Posted on January 20, 2018 at 05:54

Yes. I am using 16bit address size.