You have a ST processor (e.g. STM32F103) and a I2C device. If the device, bus, or processor gets a bit error in the I2C bus, it will lock up the bus.
After trying many solutions, this one works...
void I2C_ResetAndInit()
{
/* This shuts off power to the I2C circuit on the processor. */
I2C_DeInit(I2C1);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/* SCL pin enable */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* SDA pin enable */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOB, &GPIO_InitStructure);
I2C_StructInit(&I2C1_InitDef);
// 400 khz.
I2C1_InitDef.I2C_ClockSpeed = 100000;
I2C_Init(I2C1, &I2C1_InitDef);
I2C_Cmd(I2C1, ENABLE);
}
I2C_DeInit(I2C1);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/* SCL pin enable */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* SDA pin enable */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOB, &GPIO_InitStructure);
I2C_StructInit(&I2C1_InitDef);
// 400 khz.
I2C1_InitDef.I2C_ClockSpeed = 100000;
I2C_Init(I2C1, &I2C1_InitDef);
I2C_Cmd(I2C1, ENABLE);
}
And for the I2c Device out there on the bus...
Oh, we are using RTOS so that is the delayt and tick stuff.
void BaroResetChip()
{
if(xTaskGetTickCount() - Baro_LastErrorMessageTime > 10000)
{
Baro_LastErrorMessageTime = xTaskGetTickCount();
mainMessagePrint(ROUTE_HALL, "Baro failed, reset.");
}
I2CClearError(I2C_DEVICE_BARO);
// Turn the baro power off and then back on.
// You DID put this in your design, right?
// Also, many I2C chips have a reset line that will do the same thing.
SetPwrBaro(0);
vTaskDelay(3000);
SetPwrBaro(1);
// You DID put this in your design, right?
// Also, many I2C chips have a reset line that will do the same thing.
SetPwrBaro(0);
vTaskDelay(3000);
SetPwrBaro(1);
I2C_ResetAndInit();
}
In summary, the important pat is you must either reset or power cycle the I2C device, and you must use DeInit to power cycle the I2C internal device on the CPU.
TF
No comments:
Post a Comment