Friday, June 10, 2011

I2C Reset on ST Microsystems Processors

So,
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);
}

And for the I2c Device out there on the bus...
Oh, we are using RTOS so that is the delayt and tick stuff.

portTickType Baro_LastErrorMessageTime = 0;
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);

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: