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 01:06 AM
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.
2017-02-22 02:07 AM
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).
2017-02-22 02:14 AM
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...
2017-02-22 02:53 AM
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.
2017-02-22 02:54 AM
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=false2017-02-22 06:04 AM
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); // msbModifying 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 ?
2017-02-22 06:07 AM
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 ffMaybe I am missing something completely.2017-02-22 06:11 AM
Sigh, tried the delay with no perceivable difference in the result.
Maybe something is really odd in my setup.
2017-02-22 06:12 AM
...
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.