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

0 comments:
Post a Comment