AnsweredAssumed Answered

STM32 I2C, receiving data problem

Question asked by l..krzychu on Jun 30, 2013
Hi there,

I'm trying to communicate STM32f4-Discovery with IMU board using I2C interface. Program is getting stuck while checking the busy flag before receiving data. There is only one slave so there is nothing that can disturb the SDA line. 

Here's the code:
void I2C1_Conf()
{
    GPIO_InitTypeDef GPIO_InitStructure;
    I2C_InitTypeDef I2C_InitStructure;
  
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
  
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
  
    //GPIO Init
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; //otwarty kolektor
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOB,&GPIO_InitStructure);
  
    GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_I2C1); //SCL
    GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_I2C1); //SCA
  
    //I2C1 Init
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_ClockSpeed = 400000; //400 kHz I2C speed
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //standardowo - 50% low, 50% high
    I2C_InitStructure.I2C_OwnAddress1 = 0x00; // nie ma znaczenia, uC działa w master mode
    I2C_InitStructure.I2C_Ack = I2C_Ack_Disable; //zablokuj ACK w trakcie czytania
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // ustaw wybor
                                                                        //urzadzenia 7 bitowym adresem
    I2C_Init(I2C1,&I2C_InitStructure);
  
    I2C_Cmd(I2C1,ENABLE);
  
}
  
void I2C_Start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction)
{
    //wait until the line is free
    while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_BUSY));
  
    //send start signal
    I2C_GenerateSTART(I2Cx,ENABLE);
  
    //w8 until ev 5 is over
    while(!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_MODE_SELECT));
  
    //send appropriate addres
    I2C_Send7bitAddress(I2Cx,address,direction);
  
    if(direction == I2C_Direction_Receiver)
    {
        while(!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
    }
    if(direction == I2C_Direction_Transmitter)
    {
        while(!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
    }
}
  
void I2C_Write(I2C_TypeDef* I2Cx, uint8_t data)
{
    I2C_SendData(I2Cx,data);
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}
  
uint8_t I2C_Read_Ack(I2C_TypeDef* I2Cx)
{
    I2C_AcknowledgeConfig(I2Cx, ENABLE);
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED));
  
    uint8_t data = I2C_ReceiveData(I2Cx);
    return data;
}
  
uint8_t I2C_Read_Nack(I2C_TypeDef* I2Cx)
{
    I2C_AcknowledgeConfig(I2Cx, DISABLE);
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED));
  
    uint8_t data = I2C_ReceiveData(I2Cx);
    return data;
}
  
void I2C_Stop(I2C_TypeDef* I2Cx)
{
    I2C_GenerateSTOP(I2Cx,ENABLE);
}
  
void MPU_Init()
{
    I2C_Start(I2C1,MPU_ADDRESS,I2C_Direction_Transmitter);
    I2C_Write(I2C1,CONFIG);
    I2C_Write(I2C1,0b00000010);
    I2C_Stop(I2C1);
  
    I2C_Start(I2C1,MPU_ADDRESS,I2C_Direction_Transmitter);
    I2C_Write(I2C1,ACCEL_CONFIG);
    I2C_Write(I2C1,0b00001011);
    I2C_Stop(I2C1);
  
    I2C_Start(I2C1,MPU_ADDRESS,I2C_Direction_Transmitter);
    I2C_Write(I2C1,GYRO_CONFIG);
    I2C_Write(I2C1,0b000010000);
    I2C_Stop(I2C1);
}
  
int I2C_GetSensorValues()
{
    uint8_t pom[2];
    int Sensor;
  
    //read temperature H
    I2C_Start(I2C1,MPU_ADDRESS,I2C_Direction_Transmitter);
    I2C_Write(I2C1,TEMP_OUT_H);
    I2C_Start(I2C1,MPU_ADDRESS,I2C_Direction_Receiver); //zawiesza się w trakcie wykonywania tej funkcji
    pom[0] = I2C_Read_Nack(I2C1);
    I2C_Stop(I2C1);
  
    //read temperature L
    I2C_Start(I2C1,MPU_ADDRESS,I2C_Direction_Transmitter);
    I2C_Write(I2C1,TEMP_OUT_L);
    I2C_Start(I2C1,MPU_ADDRESS,I2C_Direction_Receiver);
    pom[1] = I2C_Read_Nack(I2C1);
    I2C_Stop(I2C1);
  
    Sensor = (pom[0]<<8) + pom[1];
  
    return Sensor;
}

In main.c functions are called respectively:
-I2C_Init()
-MPU_Init()
-I2C_GetSensorValues()

Program hangs during I2C_GetSensorValues() function, in line :
while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_BUSY));

Thanks for any help!

Outcomes