cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 Discovery - I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED

predrag10
Associate II
Posted on January 02, 2014 at 18:26

Hello everyone. I probably have some usual problem about i2c communication. Namely, I have the following code and trying to read MPU6050 WHO_AM_I register(http://www.invensense.com/mems/gyro/mpu6050.html). The address of MPU6050 is 0x68 << 1(0xD0) but when i try to read it i stuck at

while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

The whole code is given:

//#include ''MPU6050.h''

#include ''stm32f4xx_i2c.h''

#include ''stm32f4xx_gpio.h''

#include ''stm32f4xx_rcc.h''

//int16_t AccelGyro[6]={0};

int main()

{

    int i = 0;

    GPIO_InitTypeDef GPIO_InitStruct;

    I2C_InitTypeDef I2C_InitStruct;

    u8* pBuffer;    

    

    // enable clock for SCL and SDA pins

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

    

  // enable APB1 peripheral clock for I2C1

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; // we are going to use PB6 and PB7

    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;            // set pins to alternate function

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;        // set GPIO speed

    GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;            // set output to open drain --> the line has to be only pulled low, not driven high

  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;            // enable pull up resistors

    GPIO_Init(GPIOB, &GPIO_InitStruct);                    // init GPIOB

    

    // Connect I2C1 pins to AF  

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_I2C1);    // SCL

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1); // SDA    

    

    

    // configure I2C1

    I2C_InitStruct.I2C_ClockSpeed = 100000;         // 100kHz

    I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;            // I2C mode

    I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;    // 50% duty cycle --> standard

    I2C_InitStruct.I2C_OwnAddress1 = 0x00;            // own address, not relevant in master mode

    I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;        // disable acknowledge when reading (can be changed later on)

    I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_10bit; // set address length to 7 bit addresses

    I2C_Init(I2C1, &I2C_InitStruct);                // init I2C1    

    

    // enable I2C1

    I2C_Cmd(I2C1, ENABLE);        

    

    /* While the bus is busy */

  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));

  /* Send START condition */

  I2C_GenerateSTART(I2C1, ENABLE);

  /* Test on EV5 and clear it */

  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

  /* Send MPU6050 address for write */

  I2C_Send7bitAddress(I2C1, 0xD0, I2C_Direction_Transmitter);

  /* Test on EV6 and clear it */

  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

  /* Clear EV6 by setting again the PE bit */

  I2C_Cmd(I2C1, ENABLE);

  /* Send the MPU6050's internal address to write to */

  I2C_SendData(I2C1, 0x75);

  /* Test on EV8 and clear it */

  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

  /* Send STRAT condition a second time */

  I2C_GenerateSTART(I2C1, ENABLE);

  /* Test on EV5 and clear it */

  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

  /* Send MPU6050 address for read */

  I2C_Send7bitAddress(I2C1, 0xD1, I2C_Direction_Receiver);

  /* Test on EV6 and clear it */

  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

4 REPLIES 4
chen
Associate II
Posted on January 02, 2014 at 18:39

Hi

''I probably have some usual problem about i2c communication.''

Do you know the I2C protocol?

http://en.wikipedia.org/wiki/I%C2%B2C

''when i try to read it i stuck at

while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));''

Looking at the code - you will get to the while() statement in a few nano seconds.

http://en.wikipedia.org/wiki/Nano-

I think you device will not be ready in that amount of time!

This is not just a coding problem - this is 'understand your system/electronics' problem!

predrag10
Associate II
Posted on January 02, 2014 at 18:49

Thank you sung.chen_chung,

I am familiar with the i2c, and i am using this http://eliaselectronics.com/stm32f4-tutorials/stm32f4-i2c-master-tutorial/ as a reference. I don't see any delays between the I2C command so I assumed that my solution will work. What do you suggest?

chen
Associate II
Posted on January 02, 2014 at 19:00

Hi

Strictly speaking ''I think you device will not be ready in that amount of time!''

is my intuitive guess.

To really see what is going on - put an oscilloscope on the data and clock and see what is happening.

If it is due to the device not being ready - put in a 100ms delay before the I2C access.

OR try triggering the I2C access from a button push.

predrag10
Associate II
Posted on January 02, 2014 at 19:15

Thanks, I added a for loop with __NOP() and it is working now. I don't have oscilloscope since I am on a vacation 🙂 Anyway, how to do it in a smarter way(asynchronously)?