STM32 I2C, Problem with end of read sequence

I’m trying to setup communication between an STM32F103RET6 and a MPU-9150 over I2C. After some tweaking I have got the write request to work but I have problem with read requests. I can see on the logic analyzer that it clock out 8 extra clock cycles, don’t set the stop signal and leave SDA low. In the sequence below I try to read 6 bytes and then stop.

This is my first I2C project so I’m not sure what to look for. Anyone recognizing this behavior and can give some ideas about possible errors to look for?

http://www.guzzzt.com/stuff/images/ledc … roblem.png

My program looks something like this:

....
while (--cnt>0)                         // while more than one byte to read
      {
        *(buffer++) = I2C_read_ack(Open_I2C); // read next databyte from I2C device
      }
      *(buffer) = I2C_read_nack(Open_I2C);    // read last databyte from I2C device
    }
  }

  I2C_stop(Open_I2C);                         // stop the transmission

....


static int I2C_read_ack(I2C_TypeDef* I2Cx)
{
 
 // enable acknowledge of received data
  I2C_AcknowledgeConfig(I2Cx, ENABLE);
  // wait until one byte has been received
  while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED))
  {
  }
  // read data from I2C data register and return data byte
  return I2C_ReceiveData(I2Cx);
}

static int I2C_read_nack(I2C_TypeDef* I2Cx)
{
  // Disable acknowledge of received data
  I2C_AcknowledgeConfig(I2Cx, DISABLE);
  // wait until one byte has been received
  while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED))
  {
  }

  // read data from I2C data register and return data byte
  return I2C_ReceiveData(I2Cx);

static int I2C_stop(I2C_TypeDef* I2Cx)
{
  // Send I2C1 STOP Condition
  I2C_GenerateSTOP(I2Cx, ENABLE);
  return OK;
}

You probably need to tell the hardware it needs to generate a stop condition before reading the last byte. Check the STM32 device documentation to be sure.

UhClem, thank you very much, that was exactly the problem. I just moved the stop enable call before the last I2C_read_nack() and now the read request works as they should too.

Hey, I am also using STM32F103 family and MPU9150.

As this is my first time, I had problem when using I2C to connect with the sensor(MPU9150).

the first one is the program show an error for the slave address if I use define word.

#define SLAVE_ADDRESS 0xD0; //MPU9150 adress when Low

thus, without using the define sentence, I directly write the address and no error came out.

I2C_start(I2C1, 0xD0, I2C_Direction_Transmitter);

[at first i wrote like this

I2C_start(I2C1, SLAVE_ADDRESS, I2C_Direction_Transmitter);

]

the second problem is the main problem which I still cannot solve it.

which is, the program stop at line [while( !I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) );].

if you noticed, i put the some string to usart port as i want to check where the program stop.

can anybody help me.

this the function to read through i2c

uint8_t I2C_read_ack(I2C_TypeDef* I2Cx){

	USART_puts(USART2, "i2c_read function!\r\n");

	// enable acknowledge of recieved data
	I2C_AcknowledgeConfig(I2Cx, ENABLE);

	USART_puts(USART2, "i2c_read acknowledged!\r\n");

	// wait until one byte has been received
	while( !I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) );   //here is where it stop

	USART_puts(USART2, "i2c_read event checked!\r\n");

	// read data from I2C data register and return data byte
	uint8_t data = I2C_ReceiveData(I2Cx);

	USART_puts(USART2, "i2c_read data received!\r\n");

	return data;
}

Your first problem with define is that you use them as C program lines but they should be used more like text-reuse lines before compilation. So “;” and the comment is all inserted on the line where you use the define.

#define SLAVE_ADDRESS 0xD0; //MPU9150 adress when Low

I2C_start(I2C1, SLAVE_ADDRESS, I2C_Direction_Transmitter);

this will look something like this for the compiler:

I2C_start(I2C1, 0xD0; //MPU9150 adress when Low, I2C_Direction_Transmitter);

So better to instead write:

//MPU9150 adress when Low
#define SLAVE_ADDRESS 0xD0

I2C_start(I2C1, SLAVE_ADDRESS, I2C_Direction_Transmitter);

For your second problem I have attached the i2c files I use so you can compare. My own project is not finished so the code is not cleaned up but the i2c stuff seems to work.

The end of line comment in the define causes no trouble at all because all comments are removed before the #define is processed. The problem is the semi-colon.

Hey all, thanks for your help.

I manage to make the 12c stuff works but i’d face one more problem which is the data received == the register that i want to read from. i.e : i want to read from the 0x75 register, then i sent the command through i2c but i got back 0x75 instead of the data inside the register.

I’d already manage to fix the problem.

thank you very much for you guys help!!!