2013-06-30 08:34 AM
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!