cancel
Showing results for 
Search instead for 
Did you mean: 

I2C Problem - read / write

nareshkumar
Associate
Posted on February 14, 2012 at 04:33

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.

2 REPLIES 2
Stm32User
Associate II
Posted on February 16, 2012 at 13:11

There are issues with the I2C unit on the STM8L devices.  See the errata for your device. There are problems if events are not handled in a timely manner, which is why it works if you slow down the clock to the I2C module. There is a workaround described in an app note which uses a timer to generate interrupts with high priority to ensure the events are handled quickly enough, but its messy.  I had the same issues as you communicating with serial eeproms and even after implementing the ''fix'' it wasn't completely reliable in my system, so I wrote my own bitbashed code.

nareshkumar
Associate
Posted on March 01, 2012 at 10:00

Thank you Patrick for your kind feedback i will try to check errata and could you help me with bit bash method code so that i could give it a try to solve my problem.