cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F407 I2C ADDR bit not being set

Defensive
Associate II

Hi, Im using my own I2C library but after i write the device adress when i receive SB interrupt the adress bit never seems to be set to 1. I have tried testing it with HAL and it seems to work fine. I would be happy if someone could help

void I2C_EventInterruptHandler(I2C_Com* i2c)
{
	uint8_t temp;

	//Check if event interrupt bit is set
	if(I2C_CheckBitStatus(&i2c->i2cReg->I2C_CR2, 9))
	{
		//Start condition
		if(I2C_CheckBitStatus(&i2c->i2cReg->I2C_SR1, 0))
		{
			temp = i2c->i2cReg->I2C_SR1;

			i2c->i2cReg->I2C_DR = i2c->deviceAddress;
		}

		//Check for address sent
		if(I2C_CheckBitStatus(&i2c->i2cReg->I2C_SR1, 1))
		{
			//Check if its in read mode and if rxLegth is 1
			if(i2c->deviceAddress & 1 && i2c->rxLength == 1)
			{
				//Disable ack
				i2c->i2cReg->I2C_CR1 &= ~(1 << 10);
				i2c->i2cReg->I2C_CR1 |= (1 << 9);
			}

			temp = i2c->i2cReg->I2C_SR1;
			temp = i2c->i2cReg->I2C_SR2;
		}

		//Check for tx/rx interrupt bit
		else if(I2C_CheckBitStatus(&i2c->i2cReg->I2C_CR2, 10))
		{
			//tx interrupt
			if(I2C_CheckBitStatus(&i2c->i2cReg->I2C_SR1, 7))
			{
				I2C_TxInterruptHandler(i2c);
			}

			//rx interrupt
			if(I2C_CheckBitStatus(&i2c->i2cReg->I2C_SR1, 6))
			{
				I2C_RxInterruptHandler(i2c);
			}
		}

		//Check for BFT bit
		else if(I2C_CheckBitStatus(&i2c->i2cReg->I2C_SR1, 2))
		{
			I2C_BFTInterruptHandler(i2c);
		}


		//Check for Stop bit
		else if(I2C_CheckBitStatus(&i2c->i2cReg->I2C_SR1, 4))
		{

		}
	}

}

 

6 REPLIES 6
Imen.D
ST Employee

Hello @Defensive ,

Check the SR1 and SR2 registers for the ADDR bit, as mentioned in the RM0090: this bit is cleared by software reading SR1 register followed reading SR2, or by hardware when PE=0. 

Reading I2C_SR2 after reading I2C_SR1 clears the ADDR flag, even if the ADDR flag was set after reading I2C_SR1. Consequently, I2C_SR2 must be read only when ADDR is found set in I2C_SR1 or when the STOPF bit is cleared.

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen

Hi, sorry for the late response. The problem is that the ADDR bit is not being sent, which should happen after EV5 (Reading SR1 and writing to DR) the solution you are proposing is for clearing the ADDR bit.

TDK
Super User

Is the slave acknowledging the address? Can you show a plot of SDA/SCL that confirms this?

  • If slave does not respond, ADDR should not be set.
  • If slave does respond, ADDR gets set. Reading SR1 from code or from the debugger will clear it.
If you feel a post has answered your question, please click "Accept as Solution".

Hi, ACK fault seems to happen with my library but not with HAL.

Read SR1 once at the start of the handler and process each bit in there that is set. Look at HAL library for how it's done correctly. Don't read it and set it to a variable ad hoc. That has consequences.

If you feel a post has answered your question, please click "Accept as Solution".

Isnt the way HAL reads the register same? Creating a temp var and assigning it. For example to clear the ADDR flag it uses this. Also doing what you did didnt work.

#define __HAL_I2C_CLEAR_ADDRFLAG(__HANDLE__)    \
  do{                                           \
    __IO uint32_t tmpreg = 0x00U;               \
    tmpreg = (__HANDLE__)->Instance->SR1;       \
    tmpreg = (__HANDLE__)->Instance->SR2;       \
    UNUSED(tmpreg);                             \
  } while(0)