AnsweredAssumed Answered

I2C Problem - read / write

Question asked by yata.naresh_kumar on Feb 14, 2012
Latest reply on Mar 1, 2012 by yata.naresh_kumar
Hi All,
   I have problem with my I2c while communicating with Gyro, i have configured my micro as master mode with standard mode , Some times SCL and SDA go low after i receive some bytes from gyro. i am using STM8l151G3 micro.
I have checked rise time and fall time , they are correct , i couldn't figure out why this is happening , i am reading one byte of data from gyro using polling method.If i decrease clk frequency to 80Khz then it starts working fine. Please check my code for I2c communication below and let me know any corrections to be done.

Read procedure for one byte is as shown below.

uint8_t GyroRead(uint16_t ucGyro_reg_Address)
{
    uint8_t ucReceivedData;
    uint8_t    ucFlag1;
    uint8_t ucFlag2;
    uint8_t ucFlag3;

    /* While the bus is busy */
    while (GetI2cFlagStatus(I2C1, I2C_FLAG_BUSY))
    {
        ;
    }
    
    /* Send START condition */
    GenerateStartBit(I2C1, ENABLE);
    /* Test on EV5 and clear it */
    while (!CheckEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
    {
        ;
    }

    /* Send Gyro device address for write */
    Send7BitAddress(I2C1, (uint8_t)DEVICE_ADDRESS, I2C_Direction_Transmitter);
    /* Test on EV6 and clear it */
    while (!CheckEventStatus(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
    {
        ;
    }

    /* Send the GYRO's internal address to write to */
    SendData(I2C1, (uint8_t) ucGyro_reg_Address);
    /* Test on EV8 and clear it */
    while (!CheckEventStatus(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
    {
        ;
    }
    
    /* Send START condition a second time */
    GenerateStartBit(I2C1, ENABLE);
    /* Test on EV5 and clear it */
    while (!CheckEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
    {
        ;
    }

    /* Send Gyro address for read */
    Send7BitAddress(I2C1, (uint8_t)DEVICE_ADDRESS, I2C_Direction_Receiver);
    /* Test on EV6 and clear it */
    while (!CheckEventStatus(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
    {
        ;
    }
    
    /*Below Method can be used to receive only one byte of data*/
    
    /* Disable Acknowledgement */
    AcknowledgeConfig(I2C1, DISABLE);
    
    /*Clear ADDR flag , reading status reg SR1 followed by SR3 clears ADDR bit*/
    ucFlag1 = I2C1->SR1;
    ucFlag2 = I2C1->SR3;

    /* Send STOP Condition */
    StopBitI2c(I2C1, ENABLE);
    
    /* Poll on RxNE Flag */
    while ((GetI2cFlagStatus(I2C1, I2C_FLAG_RXNE) == CLEAR))
    {
        ;
    }

    /* Read a byte from the selected Gyro register */
    ucReceivedData = ReceiveData(I2C1);

    /* Enable Acknowledgement to be ready for another reception */
    AcknowledgeConfig(I2C1, ENABLE);

    return ucReceivedData;
}

Is my sequence for reading one byte is correct ????

Write procedure is as below

void GyroWrite(uint16_t ucGyro_reg_Address , uint8_t ucGyro_reg_Value)
{    
    /* Send START condition */
    GenerateStartBit(I2C1, ENABLE);    
    /* Test on EV5 and clear it */
    while (!CheckEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
    {
          ;
    }            

    /* Send slave Address for write , 7 bit address mode*/
    Send7BitAddress(I2C1, (uint8_t)DEVICE_ADDRESS, I2C_Direction_Transmitter);
    /* Test on EV6 and clear it */
    while (!CheckEventStatus(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
    {
          ;
    }

    /* Send the GYRO's internal address to write to */
    SendData(I2C1, (uint8_t) ucGyro_reg_Address);
    /* Test on EV8 and clear it */
    while (!CheckEventStatus(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
    {
          ;
    }
    
    /* Send the GYRO's address value */
    SendData(I2C1, ucGyro_reg_Value);
    /* Test on EV8 and clear it */
    while (!CheckEventStatus(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
    {
          ;
    }

    /* Send STOP condition */
    StopBitI2c(I2C1, ENABLE);
}

Can anyone help me solve this problem.

Outcomes