0
\$\begingroup\$

I am doing I2C project with MPU6050 using STM32F4DISCOVERY board. The ADDR bit in SR1 register is clearing in one instruction execution without reading SR2 register. Because of clearing ADDR bit, I can't do acknowledge disable is made during EV6 in single byte receiving case.

The datasheet states:

ADDR: Address sent (master mode)/matched (slave mode) This bit is cleared by software reading SR1 register followed reading SR2.

In case a single byte has to be received, the Acknowledge disable is made during EV6 (before ADDR flag is cleared) and the STOP condition generation is made after EV6.

If I write any instruction (or declaration) between I2C->DR=address|0 and while(!(I2C2->SR1 & (1<<1))) in below code, then ADDR flag is cleared without reading the SR2 register (I2C2->SR2).

if(direction==i2c_transmitter_mode)
{

    I2C2->DR = address | 0;//SEND ADDRESS WITH ZERO LAST BIT
    while(!(I2C2->SR1 & (1<<1)))
    {
        if(--i2c1_timeout==00)
        {
            return 1;
        }
    }
    I2C2->SR2;
    return 0;

}

How can I fix this problem?

\$\endgroup\$
0
\$\begingroup\$

You can fix it by using the correct bit. ADDR bit is not 1<<7 but 1<<1.

\$\endgroup\$
  • \$\begingroup\$ Sir,you are right.But the waiting loop is being continuing with ADDR. Both ADDR AND TXE are set after transmission of address.But ADDR is reset immediately after set .so,i am using TXE bit for waiting and checking AF flag.I am getting WHO_AM_I register value of MPU6050.But problem is ADDR \$\endgroup\$ – naresh Oct 19 '19 at 5:31
  • \$\begingroup\$ much more issues in those 5 lines of code OP has :) \$\endgroup\$ – P__J__ Oct 19 '19 at 12:07
0
\$\begingroup\$
  1. Do not use magic numbers like 1<<1 1<<7 on those complex uCs. Use human readable definitions.

  2. Your sequence is wqrong

    I2C1 -> CR1 |= I2C_CR1_START;
    while(!(I2C1 -> SR1 & I2C_SR1_SB ));
    I2C1 -> DR = addr;
    while(!(I2C1 -> SR1 & I2C_SR1_ADDR));
    (void)I2C1 -> SR2;

it is a very simple version - you should add timeouts, error checking, address ACK checking etc. But it shows the general idea.

  1. I2C2->DR = address | 0; - it does not clear the last bit. Actually it does nothing. My advice - read about bitwise operators

to clear the particular bit:

address &= ~(1 << bitnumber);
I2C2->DR = address;

or for the bit zero

address &= ~(1 << 0);
I2C2->DR = address;

why I did not write address &= 0xfffffffe; - because it less understandable for humans. If you see the code with ~ you know that someone is zeroing some bits.

\$\endgroup\$
  • \$\begingroup\$ sir,i followed below sequence using functions l I2C1 -> CR1 |= I2C_CR1_START; while(!(I2C1 -> SR1 & I2C_SR1_SB )); I2C1 -> DR = addr; while(!(I2C1 -> SR1 & I2C_SR1_ADDR)); (void)I2C1 -> SR2; \$\endgroup\$ – naresh Oct 19 '19 at 19:44
  • \$\begingroup\$ I will follow your suggestions.I am getting WHO_AM_I register value of MPU6050.But problem is ADDR. please help me.Thank you for your reply \$\endgroup\$ – naresh Oct 19 '19 at 19:59
  • \$\begingroup\$ I don't have intention to clear the address.my intention to sent 0xD0 address to DR register in master transmission mode and send 0xD1 for receiving mode using I2C2->DR = address | 1. \$\endgroup\$ – naresh Oct 19 '19 at 20:09
  • \$\begingroup\$ | is a or operator. Oring with zero does nothing. U gave the way of clearing particular bits \$\endgroup\$ – P__J__ Oct 19 '19 at 21:12
  • \$\begingroup\$ sir,leave it about | operator.please concentrate on my ADDR problem \$\endgroup\$ – naresh Oct 20 '19 at 4:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.