cancel
Showing results for 
Search instead for 
Did you mean: 

I2C1 hangs at while(!I2C_CheckEvent(MPU6050_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

harinath
Associate III
Posted on July 19, 2012 at 09:48

I have STM32-P103 board which uses STM32F103RB micro. I connected I2C sensors to I2C2 pins as shown below :

0690X000006050uQAA.png I use only 4 pins of the sensor, SCL, SDA, Vcc, GND.I have the following Initialization code & reading code:

#define MPU6050_I2C I2C2
#define MPU6050_I2C_RCC_Periph RCC_APB1Periph_I2C2
#define MPU6050_I2C_Port GPIOB
#define MPU6050_I2C_SCL_Pin GPIO_Pin_10
#define MPU6050_I2C_SDA_Pin GPIO_Pin_11
#define MPU6050_I2C_RCC_Port RCC_APB2Periph_GPIOB
#define MPU6050_I2C_Speed 100000
void
MPU6050_I2C_Init(
void
)
{
I2C_InitTypeDef I2C_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable I2C and GPIO clocks */
RCC_APB1PeriphClockCmd(MPU6050_I2C_RCC_Periph, ENABLE);
RCC_APB2PeriphClockCmd(MPU6050_I2C_RCC_Port, ENABLE);
/* Configure I2C pins: SCL and SDA */
GPIO_InitStructure.GPIO_Pin = MPU6050_I2C_SCL_Pin | MPU6050_I2C_SDA_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(MPU6050_I2C_Port, &GPIO_InitStructure);
I2C_DeInit(MPU6050_I2C);
/* I2C Peripheral Enable */
I2C_Cmd(MPU6050_I2C, ENABLE);
/* I2C configuration */
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0xD0;
// MPU6050 7-bit adress = 0x68, 1-bit left shifted adress = 0xD0;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = MPU6050_I2C_Speed;
/* Apply I2C configuration after enabling it */
I2C_Init(MPU6050_I2C, &I2C_InitStructure);
}
void
I2C_BufferRead(u8 slAddr, u8* pBuffer, u8 ReadAddr, u16 NumByteToRead)
{
// ENTR_CRT_SECTION();
/* While the bus is busy */
while
(I2C_GetFlagStatus(MPU6050_I2C, I2C_FLAG_BUSY));
/* Send START condition */
I2C_GenerateSTART(MPU6050_I2C, ENABLE);
/* Test on EV5 and clear it */
while
(!I2C_CheckEvent(MPU6050_I2C, I2C_EVENT_MASTER_MODE_SELECT));
/* Send
MPU6050 address (0xD0) for write */
I2C_Send7bitAddress(MPU6050_I2C, slAddr, I2C_Direction_Transmitter);
/* Test on EV6 and clear it */
while
(!I2C_CheckEvent(MPU6050_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
/* Clear EV6 by setting again the PE bit */
I2C_Cmd(MPU6050_I2C, ENABLE);
/* Send the MPU6050_Magn's internal address to write to */
I2C_SendData(MPU6050_I2C, ReadAddr);
/* Test on EV8 and clear it */
while
(!I2C_CheckEvent(MPU6050_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
/* Send STRAT condition a second time */
I2C_GenerateSTART(MPU6050_I2C, ENABLE);
/* Test on EV5 and clear it */
while
(!I2C_CheckEvent(MPU6050_I2C, I2C_EVENT_MASTER_MODE_SELECT));
/* Send MPU6050 address for read */
I2C_Send7bitAddress(MPU6050_I2C, slAddr, I2C_Direction_Receiver);
/* Test on EV6 and clear it */
while
(!I2C_CheckEvent(MPU6050_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
/* While there is data to be read */
while
(NumByteToRead)
{
if
(NumByteToRead == 1)
{
/* Disable Acknowledgement */
I2C_AcknowledgeConfig(MPU6050_I2C, DISABLE);
/* Send STOP Condition */
I2C_GenerateSTOP(MPU6050_I2C, ENABLE);
}
/* Test on EV7 and clear it */
if
(I2C_CheckEvent(MPU6050_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED))
{
/* Read a byte from the MPU6050 */
*pBuffer = I2C_ReceiveData(MPU6050_I2C);
/* Point to the next location where the byte read will be saved */
pBuffer++;
/* Decrement the read bytes counter */
NumByteToRead--;
}
}
/* Enable Acknowledgement to be ready for another reception */
I2C_AcknowledgeConfig(MPU6050_I2C, ENABLE);
// EXT_CRT_SECTION();
}

This code works fine for me as well as others. But now i use same files in another project which uses STM32F103RE micricontroller and sensor connected to I2C1 with 10k pull-ups( this time INT pin of MPU6050 connected to PB8, but not configured), rest of the things are same. 0690X00000604XiQAI.pngI also modified code to use I2C1.

#define MPU6050_I2C I2C1
#define MPU6050_I2C_RCC_Periph RCC_APB1Periph_I2C1
#define MPU6050_I2C_Port GPIOB
#define MPU6050_I2C_SCL_Pin GPIO_Pin_6
#define MPU6050_I2C_SDA_Pin GPIO_Pin_7

I call the I2C_BufferReadfunction just after initialization.Execution hangs at

/* Test on EV6 and clear it */
while
(!I2C_CheckEvent(MPU6050_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

Any helpappreciated. Below is the I2C analyzer debug information.

https://dl.dropbox.com/u/14046521/I2C_problem.png

https://dl.dropbox.com/u/14046521/I2C_good.png

Thank you #i2c #i2c #accelerometer
10 REPLIES 10
jpeacock2399
Associate II
Posted on July 19, 2012 at 16:16

Configure the SCL and SDA pins as GPIO inputs instead of alternate function at the beginning of the initialization.  Check both pins to see if either is being held low.  If so, this means an I2C peripheral is holding the pin low, usually waiting for more data or stretching the clock.

Unfortunately most I2C examples do not include the all-too-common case of a hung bus peripheral that doesn't reset properly on startup.  The usual cure, if it's the SDA line held low, is to generate 100KHz clock pulses on SCL by toggling the GPIO line until the SDA line goes hi.  This assumes there's no separate reset line for the I2C peripheral (very few have external reset).

If the SCL line is held low then you have a hardware problem, unless the peripheral is in master mode and looking for an ACK on the SDA line.  Sometimes toggling the SDA line will clear this.

  Jack Peacock

harinath
Associate III
Posted on July 20, 2012 at 07:32

Hi Jack,

1. Configured the SCL and SDA pins as GPIO inputs (GPIO_Mode_IN_FLOATING) instead of alternate function at the beginning of the initialization.  Checked both pins to see if either is being held low, they are both held low. I could not toggle the pins.

2. Configured the SCL and SDA pins as GPIO outputs instead of alternate function at the beginning of the initialization.  Checked both pins to see if either is being held low, they are both held high. I could generate square wave.

I think reset concept does not solve this problem.

Thank you
frankmeyer9
Associate II
Posted on July 20, 2012 at 10:15

I think reset concept does not solve this problem.

 

Can you assure that the external conditions have been identical in both cases ?

As you wrote:

Checked both pins to see if either is being held low, they are both held low. I could not toggle the pins.

 

That points to an external source that held the pin(s) low, which must have been an I2C device connected to this pins. If you do not know the state of those external devices exactly, the tests are guesswork. For short, the different result might not have been the result of the different GPIO initialization.

As the MPU6050 and the HMC5883 are I2C slaves, that sounds strange. I can't remember any situation where a slave is allowed to pull both SDA and SCL low simultaneously.

I would try Jacks suggestion anyway.

harinath
Associate III
Posted on July 23, 2012 at 04:45

Hi fm & Jack,

I'm rewriting my reply as there was mistake. Sorry for misleading you people.

1. Configured the SCL and SDA pins as GPIO inputs (GPIO_Mode_IN_FLOATING) instead of I2C pins.  Checked both pins to see if either is being held low, they are both held high. I tried to toggle the pins, but they are always high.

2. Configured the SCL and SDA pins as GPIO outputs instead of I2C pins.  Checked both pins to see if either is being held low, they are both held high. I could generate square wave.

My understanding from the debug picture says, The SDA has to go high & come back to low   in 10th clock cycle, But it is going high in 9th clock cycle & doesn't comes low, then SCL becomes low. This tells us that there is no acknowledgement coming from MPU6050. 

I also disconnected the SDA, SCL traces to MPU6050 on the board & connected them to a external working

http://www.sparkfun.com/products/11028

 . Still the same problem persists. 

I think reset concept does not solve this problem.

Thank you

jpeacock2399
Associate II
Posted on July 23, 2012 at 16:18

On your schematic the VLOGIC input pin on the MPU6050 doesn't seem to be connected to the I2C supply voltage.  This might explain why the MPU6050 isn't responding to I2C commands.

  Jack Peacock

harinath
Associate III
Posted on July 24, 2012 at 03:27

Hi Jack and others,

Jack & fm was right, It was my mistake that i did not connect VLOGIC pin to Supply.

 

http://www.sparkfun.com/

 breakout board schematic was the reason to commit to this mistake as it doesn't show connection of VLOGIC to supply(3.3V).

Once again thank you Jack & fm.

Harinath
flyer31
Senior
Posted on July 24, 2012 at 09:36

I2C of STM32F4 can get blocked by a slave which keeps SDA + SCL low.

In such case only possibility to restart is, to switch GPIO pin back to ''normal output'' (Alternate function off) and send out 8 clock cycles on SCL line manual. After latest 8 (or 9, 10 ) cycles the slave should recognize, that there is no ACK from master, then the slave will reset its I2C interface and all will work again.

frankmeyer9
Associate II
Posted on July 24, 2012 at 09:49

I hade a look at the MPU60x0 datasheet yesterday, and I agree with Jack.

The VLOGIC pin is listed as power supply for the logic block of the MPU6050, but for the MPU6050 only. According to the datasheet, this pin is not connected at the MPU6000 derivate.

I remember that a IMU300 which I have (from Invensense, like the MPU60x0) also has split power supply pins for analog and digital logic. That seems to be a speciality of Invensense.

vendor
Associate II
Posted on February 06, 2014 at 18:52

Good new you figured this out, but is there any reason no one suggested you use STM Gyroscope PN 

LSM330DLC ? ST is the leader in accelerometer/ gyro and MEMS technology in general,  and their support is phenomenal.