cancel
Showing results for 
Search instead for 
Did you mean: 

I²C - I2C_ReceiveData() always returning 0

benryves
Associate II
Posted on December 11, 2009 at 16:06

I²C - I2C_ReceiveData() always returning 0

4 REPLIES 4
benryves
Associate II
Posted on May 17, 2011 at 15:06

I'm attempting to read data from an I²C EEPROM (AT24C256B - 32Kx8). I've hacked the I²C example code into something pretty straightforwards (comments stripped):

Code:

CLK_DeInit();

CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);

CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSE, DISABLE, CLK_CURRENTCLOCKSTATE_DISABLE);

I2C_DeInit();

I2C_Cmd(ENABLE);

I2C_Init(100000, 0xA0, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, 16);

while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY));

I2C_GenerateSTART(ENABLE);

while (!I2C_CheckEvent(I2C_EVENT_MASTER_START_SENT));

I2C_Send7bitAddress(0xA0, I2C_DIRECTION_TX);

while (!I2C_CheckEvent(I2C_EVENT_MASTER_ADDRESS_ACKED));

I2C_ClearFlag(I2C_FLAG_ADDRESSSENTMATCHED);

I2C_SendData((u8)0);

while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));

I2C_SendData((u8)0);

while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));

I2C_GenerateSTART(ENABLE);

while (!I2C_CheckEvent(I2C_EVENT_MASTER_START_SENT));

I2C_Send7bitAddress(0xA0, I2C_DIRECTION_RX);

while (!I2C_CheckEvent(I2C_EVENT_MASTER_ADDRESS_ACKED));

I2C_ClearFlag(I2C_FLAG_ADDRESSSENTMATCHED);

for(;;) {

u8 data;

while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_RECEIVED));

data = I2C_ReceiveData();

nop();

}I've set a breakpoint on nop() and have set a watch on data. data is always set to 0, whereas I'd expect it to read one byte from the EEPROM sequentially, starting from address 0. I have programmed the EEPROM with an external programmer, and have verified that it has meaningful data (non-zero) at the start.

Changing the EEPROM address to something different (e.g. 0xA2) hangs the code when checking I2C_EVENT_MASTER_ADDRESS_ACKED, as you'd expect (there are no other devices on the bus), so the EEPROM appears to be responding. A logic probe on the SDA line shows it changing state when it the EEPROM is apparently being read.

I'm probably doing something daft here, sorry, but does anyone have any clues as to where?

baroudi
Associate II
Posted on May 17, 2011 at 15:06

Hi benryves,

I am seeing a strange thing !

Why the EEPROM address is the same as the STM8S chip address ?

/* I2C_SLAVE_ADDRESS7 is the adress of the STM8 chip */

I2C_Init(100000, I2C_SLAVE_ADDRESS7, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, 16);

/* EEPROM_ADDRESS is the adress of EEPROM memory */

I2C_Send7bitAddress(EEPROM_ADDRESS, I2C_DIRECTION_TX);

try to update I2C_Init with I2C_SLAVE_ADDRESS7 = 0xa3;

Let me know if it is ok.

Good luck,

benryves
Associate II
Posted on May 17, 2011 at 15:06

Thank you for your reply. I got confused by the example using 0xA0 as the STM8S chip address, as the I²C EEPROMs I have all use 0xA0 as their own address by default. I've changed it to 0xA2 (I was under the impression that the least-significant bit was used to indicate R/W, and so should be left unset) and ''success'' - it now reads 98 every time instead of 0 (the first byte on the EEPROM is 86, the letter 'V').

On a whim, I removed the Atmel AT24C256B and replaced it with a Microchip part (24LC256) which worked first time. I then went back to the original Atmel part, and that now reads data fine too! At least I've now got some results, I should be able to get something working - thank you very much. :)

Edit: Nope, it's stopped working and is returning 0s again without having changed anything. I'm getting more and more stumped...

[ This message was edited by: benryves on 10-12-2009 21:05 ]

benryves
Associate II
Posted on May 17, 2011 at 15:06

Sorry to bump this, but I've found something suspicious. The following code always returns the same value, usually 0x00 or 0xFF:

Code:

for(;;) { <BR> u8 data; <BR> while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_RECEIVED)); <BR> data = I2C_ReceiveData() <BR> nop(); // Breakpoint here to check value of data. <BR>}

However, this works fine:

Code:

for(;;) { <BR> u8 data; <BR> while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_RECEIVED)); <BR> if (data = I2C_ReceiveData()) { <BR> nop(); // Breakpoint here to check value of data. <BR> } <BR>}

I'm using the Cosmic tools. I'll do a bit more digging to see if I can find something a bit more concrete!

Edit: This works, now:

Code:

void EEPROM_Init(void) { <BR> I2C_DeInit(); <BR> I2C_Cmd(ENABLE); <BR> I2C_Init(100000, 0xB0, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, 16); <BR> while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY)); <BR>} <BR> <BR>void EEPROM_StartReading(u16 address) { <BR> I2C_GenerateSTART(ENABLE); <BR> while (!I2C_CheckEvent(I2C_EVENT_MASTER_START_SENT)); <BR> I2C_Send7bitAddress(I2C_EEPROMAddress, I2C_DIRECTION_TX); <BR> while (!I2C_CheckEvent(I2C_EVENT_MASTER_ADDRESS_ACKED)); <BR> I2C_ClearFlag(I2C_FLAG_ADDRESSSENTMATCHED); <BR> I2C_SendData((u8)(address >> 8)); <BR> while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED)); <BR> I2C_SendData((u8)address); <BR> while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED)); <BR> <BR> I2C_GenerateSTART(ENABLE); <BR> while (!I2C_CheckEvent(I2C_EVENT_MASTER_START_SENT)); <BR> I2C_Send7bitAddress(I2C_EEPROMAddress, I2C_DIRECTION_RX); <BR> while (!I2C_CheckEvent(I2C_EVENT_MASTER_ADDRESS_ACKED)); <BR> I2C_ClearFlag(I2C_FLAG_ADDRESSSENTMATCHED); <BR>} <BR> <BR>u8 EEPROM_ReadByte(void) { <BR> while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_RECEIVED)); <BR> return I2C_ReceiveData(); <BR>} <BR> <BR>int main(void) { <BR> EEPROM_Init(); <BR> EEPROM_StartReading(0x0000); <BR> <BR> for(;;) { <BR> u8 data = EEPROM_ReadByte(); <BR> nop(); <BR> } <BR>}

[ This message was edited by: benryves on 11-12-2009 20:45 ]