2009-04-22 05:10 AM
I2C 1 Always Busy
2011-05-17 04:10 AM
Hi.
I'm trying to bring up a new design based on an STM32F103ZEH6. I have a clean project based on the latest version 3 library, using STs template project for the IAR compiler. My problem is that as soon as I enable the clock to the I2C1 peripheral the busy bit in status register 2 becomes set and I am unable to clear it. I am not using the FSMC. I2C1 pins are mapped to their default locations (PortB 6 and 7). Calling I2C_DeInit(I2C1); does not reset the busy bit. Has anyone else found this behaviour? Regards Tom2011-05-17 04:10 AM
First, pull-up must be attached (about 4.7k)
Second, I think STM32's I2C is TOO smart! If SDL line is low, they wait forever until high. May be they think someone else is using the I2C line. Here is my foolish solution for the I2C bus recovery. void i2c_bus_reset(void) { u32 uEvent; I2C_DeInit(I2C1); I2C1_init(); i2c_delay(); uEvent = I2C_GetLastEvent(I2C1); if(uEvent == I2C_FLAG_BUSY) { //-------------------------- // I2C bus recovery //-------------------------- I2C_Cmd(I2C1, DISABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); // generate manual STOP condition GPIO_ResetBits(GPIOB, GPIO_Pin_6); GPIO_ResetBits(GPIOB, GPIO_Pin_7); i2c_delay(); GPIO_ResetBits(GPIOB, GPIO_Pin_6); i2c_delay(); GPIO_SetBits(GPIOB, GPIO_Pin_7); i2c_delay(); i2c_delay(); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_Init(GPIOB, &GPIO_InitStructure); I2C_Cmd(I2C1, ENABLE); I2C1->CR1 = (u16)0x0401; // Enable the acknowledgement } } void i2c_delay(void) { volatile unsigned long i; for(i=0; i} ST should provide a better solution!2011-05-17 04:10 AM
I've seen this behavior on I2C with certain periphal chips that don't always reset to a clean state, or hang during a bus transaction. Remember that the lines are open collector, so anything can hold the SDA line low (I assume you DO have pull up resistors on the line).
The best solution I've found is to generate clocks on the SCL line until the SDA line goes hi. And if the slave devices have reset lines, be sure to generate a reset before initing the I2C bus.2011-05-17 04:10 AM
Hi
Yes, I do have pull-ups on the bus and there is only a single slave device. Unfortunatly there is no reset for the slave. I'll try manually clocking the SCL line and monitor the SDA line for a change of state. Thank you for your advice.