2017-02-22 12:59 AM
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 ffwhich 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.2017-02-22 06:50 AM
Add 10msec delay between each write. Programming start after the stop bit.
Or try
2017-02-22 07:09 AM
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.
2017-02-22 07:21 AM
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).
2017-02-22 07:44 AM
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:
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.
2017-02-23 07:02 AM
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=false2017-02-24 01:00 AM
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.
2017-02-28 05:04 AM
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.2018-01-19 04:46 AM
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 ?
2018-01-19 04:53 AM
Hi,
Are you sure you are using 16Bit addres size with HAL_I2C_Mem_Write and Read functions?
Regards
2018-01-19 09:54 PM
Yes. I am using 16bit address size.