Skip to main content
Visitor II
August 24, 2025
Question

STM32F407 I2C ADDR bit clearing itself and interrupt problems

  • August 24, 2025
  • 1 reply
  • 295 views

Hi, Im new to STM32 and writing a bare metal interrupt based i2c library. For some reason addr bit clears itself automatically even though im not reading sr1 and sr2. I also have problems with debug mode, if i decide to step over the function that sets up the interrupt for I2C1_EV_IRQ it sometimes causes debugger to skip the interrupt, it happens randomly. I had some problems with the built in debugger.

 

void I2C_ReceiveData(I2C_Com* i2c, uint8_t address, uint8_t deviceRegister, uint8_t* data, uint8_t length)
{
	if(!i2c->isBusy)
	{
		i2c->i2cReg->I2C_CR1 |= (1 << 10);

		i2c->deviceAddress = address;
		i2c->deviceAddress <<= 1;

		i2c->deviceRegister = deviceRegister;
		i2c->registerNotSent = 1;

		i2c->txLength = 0;

		i2c->rxBuffer = data;
		i2c->rxLength = length;

		i2c->isBusy = 1;
		i2c->repeatedStart = 1;

		i2c->i2cReg->I2C_CR2 |= (1 << 9);
		i2c->i2cReg->I2C_CR2 |= (1 << 10);

		SetNVIC(I2C1_EV_IRQ_NUM, 1);

		//Start condition
		i2c->i2cReg->I2C_CR1 |= (1 << 8);
	}
}

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
 //ADDR BIT CLEARS ITSELF CANT GET INTO THIS IF STATEMENT
		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))
		{

		}
	}

}

void I2C1_EV_IRQHandler()
{
	I2C_EventInterruptHandler(&i2c1Com);
}

 

    This topic has been closed for replies.

    1 reply

    Super User
    August 24, 2025

    What leads you to believe the bit is clearing itself?

    Reading registers with the debugger has the same consequences as reading them with the program. Namely, reading SR1 and SR2 will clear the ADDR bit.

    TDK_0-1756042640498.png

     

    DefensiveAuthor
    Visitor II
    August 24, 2025

    I was checking the SR1 register for the addr bit in the SFR. Is that what causes the addr bit to clear itself?