AnsweredAssumed Answered

My I2C is very slow, need help :)

Question asked by prieur.jean on Feb 18, 2015
Latest reply on Feb 18, 2015 by Clive One
Hello everybody,

I have a problem with I2C on STM32F427. I communicate with a touchpad controller: everything is OK, I can configure this I2C controller and get its datas.

But when I communicate it takes a lot of time and I can see my uC slowing down. It's strange because I don't send it a lot of datas and it don't send me a lot of datas. And the I2C clock speed is 400kHz.

And even sometimes the communication freeze my program...

I attached my code below, can you please advise me on what going wrong?

Thanks a lot and have a good day!


I2C DRIVER:

/* Direction = I2C_Direction_Transmitter or I2C_Direction_Receiver */
void I2C1_Repeated_Start(uint8_t direction)
{
    // Send I2C1 START condition
    I2C_GenerateSTART(I2C1, ENABLE);
 
    // wait for I2C1 EV5 --> Slave has acknowledged start condition
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
 
    // Clear flag
    I2C_ClearFlag(I2C1, I2C_FLAG_AF);
 
    // Send slave Address for write
    I2C_Send7bitAddress(I2C1, TP_ADRESS<<1, direction);
 
    if(direction == I2C_Direction_Transmitter)
    {
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
    }
    else if(direction == I2C_Direction_Receiver)
    {
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
    }
}
 
/* Direction = I2C_Direction_Transmitter or I2C_Direction_Receiver */
void I2C1_Start(uint8_t direction)
{
    // wait until I2C1 is not busy anymore
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
 
    // Send I2C1 START condition
    I2C_GenerateSTART(I2C1, ENABLE);
 
    // wait for I2C1 EV5 --> Slave has acknowledged start condition
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
 
    // Clear flag
    I2C_ClearFlag(I2C1, I2C_FLAG_AF);
 
    // Send slave Address for write
    I2C_Send7bitAddress(I2C1, TP_ADRESS<<1, direction);
 
    /* wait for I2C1 EV6, check if
     * either Slave has acknowledged Master transmitter or
     * Master receiver mode, depending on the transmission
     * direction
     */
    if(direction == I2C_Direction_Transmitter)
    {
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
    }
    else if(direction == I2C_Direction_Receiver)
    {
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
    }
}
 
void I2C1_Stop(void)
{
    // Send I2C1 STOP Condition
    I2C_GenerateSTOP(I2C1, ENABLE);
 
    // Clear flag
    I2C_ClearFlag(I2C1, I2C_FLAG_AF);
}
 
void I2C1_Wr(uint8_t data)
{
    I2C_SendData(I2C1, data);
    // wait for I2C1 EV8_2 --> byte has been transmitted
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
 
    // Clear flag
    I2C_ClearFlag(I2C1, I2C_FLAG_AF);
}
 
uint8_t I2C1_Read_Ack(void)
{
    // enable acknowledge of recieved data
    I2C_AcknowledgeConfig(I2C1, ENABLE);
    // wait until one byte has been received
    while( !I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) );
    // read data from I2C data register and return data byte
    uint8_t data = I2C_ReceiveData(I2C1);
 
    // Clear flag
    I2C_ClearFlag(I2C1, I2C_FLAG_AF);
 
    return data;
}
 
uint8_t I2C1_Read(void)
{
    // enable acknowledge of recieved data
    I2C_AcknowledgeConfig(I2C1, DISABLE);
    // wait until one byte has been received
    while( !I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
    // read data from I2C data register and return data byte
    uint8_t data = I2C_ReceiveData(I2C1);
 
    // Clear flag
    I2C_ClearFlag(I2C1, I2C_FLAG_AF);
 
    return data;
}


CALCULATE FINGER POSITION:

void CALCULATE_POSITION(void)
{
       I2C1_Start(I2C_Direction_Transmitter);   // Communication started
       I2C1_Wr(0x01);                                      // Send data address
       I2C1_Repeated_Start(I2C_Direction_Receiver);    // Issue repeated start signal
       info = I2C1_Read_Ack();                             // Read the data (01 Info Byte)
 
       if (info > 128){                                    // If there are any active coordinates, read all the bytes
 
          // Touch 1
          ID_1 = I2C1_Read_Ack();                                 // Read the data (02 ID 1)
          x_h_1 = I2C1_Read_Ack();                                // Read the data (03 X 1 High Byte)
          x_l_1 = I2C1_Read_Ack();                                // Read the data (04 X 1 Low Byte)
          y_h_1 = I2C1_Read_Ack();                                // Read the data (05 Y 1 High Byte)
          y_l_1 = I2C1_Read_Ack();
          t_h_1 = I2C1_Read_Ack();                                // Read the data (07 Touch Strength 1 High Byte)
          t_l_1 = I2C1_Read();                                // Read the data (08 Touch Strength 1 Low Byte)
 
          I2C1_Stop();                                        // Close communication window
 
                  }
}

Outcomes