cancel
Showing results for 
Search instead for 
Did you mean: 

How to checkif an EEPROM exists at I²C?

KSchü.2
Associate II

Hello!

I'm trying to detect if a removable EEPROM exists in a given system, but I ran into some problems.

With configuration

 STM_enableRCCAPB1PeriphClock( RCC_APB1Periph_I2C1, ENABLE );

 STM_resetRCCAPB1PeriphCmd( RCC_APB1Periph_I2C1, DISABLE );

 I2C_Cmd( m_pEE_I2C_TYPE, ENABLE );

 I2C_ITConfig( m_pEE_I2C_TYPE, I2C_IT_ERR, ENABLE );

 I2C_InitStructure.I2C_Mode        = EE_I2C_MODE;

 I2C_InitStructure.I2C_DutyCycle      = EE_I2C_DUTY_CYCLE;

 I2C_InitStructure.I2C_OwnAddress1     = EE_I2C_OWN_ADDRESS;

 I2C_InitStructure.I2C_Ack         = EE_I2C_ACK;

 I2C_InitStructure.I2C_AcknowledgedAddress = EE_I2C_ACK_ADDR;

 I2C_InitStructure.I2C_ClockSpeed     = EE_I2C_CLOCK_SPEED;

 GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6 BITOR GPIO_Pin_7;

 GPIO_InitStructure.GPIO_Speed  = GPIO_Speed_50MHz;

 GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_OD;

I'm basically trying:

 check if busy: I2C_GetFlagStatus( m_pI2C1, I2C_FLAG_BUSY );

if not, start:    I2C_GenerateSTART( m_pI2C1, ENABLE );

control: u32_checkEvent( I2C_EVENT_MASTER_MODE_SELECT );

set address: I2C_Send7bitAddress( m_pI2C1, u8DevAddr, I2C_Direction_Transmitter );

control: u32_checkEvent( I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED );

but the last checkEvent() simply hangs up if the addressed EEPROM doesn't exist.

I tried to replace it with

if ( ( ( ( *(__IO uint32_t *)m_pI2C1 + 0x14u ) ) & 0x400u ) == (uint32_t)RESET );

but didn't get the expected results.

Looking into the individual bits

            SR1Register = m_pI2C1->SR1; 

            SBBit  = SR1Register & 0x001u;

            ADDRBit = SR1Register & 0x002u;

AFBit = SR1Register & 0x0400u;

I noticed the behavior of AF and SB seem to be as expected, but ADDR is never set, not even if there's an EEPROM connected.

But using this method (testing AF only immediately after sending the address) in real time delivers the obviously wrong results (always okay).

On the other hand, TxE appears to be a reliable indicator of when the AF-Bit can be tested.

So my question are:

When is ADDR ever set (and for how long)?

What is the correct order to test bits (AF only when TxE if set and SB is reset)?

Is there another way to test for missing pheripherals on I²C?

3 REPLIES 3
KSchü.2
Associate II

The µC is a STM32F103 and it uses a 24AA044 from Microchip.

I started out with Ack Polling like

do {

I2C_GenerateSTART( m_pI2C1, ENABLE );

while ( ! I2C_CheckEvent( m_pI2C1, I2C_EVENT_MASTER_MODE_SELECT ) );

I2C_Send7bitAddress( m_pI2C1, u8DevAddr, I2C_Direction_Transmitter );

state = I2C_CheckEvent( m_pI2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED );

} while(state==ERROR);

but here the code stops on first call to I2C_CheckEvent() after I2C_Send7bitAddress() until saved by the watchdog.

After that I2C_Send7bitAddress(), CR1->ACK is (still) set, despite the lack of the addressed EEPROM, but SR1->AF goes up, but SR1->TxE still is 0;

so who acknowleded the address and how can AF and ACK have the same value anyway?

Hello

>> I2C_CheckEvent( m_pI2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED );

Dont call it once.. check it continously at least until TXE is set , add some extra reasonable timeout until ADDR is set(or not) few milliseconds timeout is ok.

KSchü.2
Associate II

Thanks for your tip.

How can I check if TxE is set or not?

Is it guaranteed that either TxE or AF hat to be set, so if I get any bit set I can assume my SentAddress() has been completed?

Additionally when can I expect the ADDR being set?

Even if I test this with a existing EEPROM, I never seen ADDR set (at least according to the Debugger's life register view).

Can I expect the event to be set only after one of those bits are set, earlier (at the start of adresse tranmission), or is this a race condition?

(Btw. 420ms are 10 times my main loop and 1/3 of my laziest watchdog.)