I have a code on Arduino to read the data from MPU9255 with no libraries, using it direct through I2C. I am trying to do the same on Keil uVision with Bluepill, just to learn how to use I2C with HAL Drivers.

I don't know What I am doing wrong, here is the code:

uint8_t adressMPU = 0x68;
uint8_t i2cData;
uint8_t* receive_buffer = 0;

i2cData = 0x6B;

HAL_I2C_Master_Transmit(&hi2c1, adressMPU, &i2cData, 1, 100 );  //Starts MPU
HAL_I2C_Master_Transmit(&hi2c1, adressMPU, 0, 1, 100 );
while (1)
    i2cData = 0x43; //adress of the register to read Accelerometer x axis
    HAL_I2C_Master_Transmit(&hi2c1, adressMPU, &i2cData, 1, 100 ); //set the register address

    HAL_I2C_Master_Receive(&hi2c1, adressMPU, receive_buffer, 2, 100); request 2 bytes from the register
    HAL_UART_Transmit(&huart1,receive_buffer,sizeof(receive_buffer),100); // send it to serial port


My code in Arduino that is working:

Wire.begin();                 //inicia I2C
Wire.beginTransmission(MPU);  //Inicia transmissão para o endereço do MPU


Wire.beginTransmission(MPU);      //transmite
Wire.write(0x43);                 // Endereço registrador do Gyro
Wire.endTransmission(false);     //Finaliza transmissão
Wire.requestFrom(MPU,6,true);   //requisita 6 bytes  
mediaGyroX += Wire.read()<<8|Wire.read();  //GYRO EIXO X  

Surely I am doing something wrong, but I can't see the error. Can somebody help me?

  • \$\begingroup\$ You probably need to send the 0x6B followed by 0x00 in a single HAL_I2C_Master_Transmit() call. Something like uint8_t i2cData[2] = {0x6B, 0x00}; HAL_I2C_Master_Transmit(&hi2c1, adressMPU, &i2cData, 2, 100 ); \$\endgroup\$ – brhans Feb 12 '18 at 20:54
  • \$\begingroup\$ I have tried, but does not work \$\endgroup\$ – Vinícius Jean Ferreira Feb 12 '18 at 21:03

For STM32 HAL define the slave address as uint8_t adressMPU = (0x68<<1);, because if you check the register description:

enter image description here

in 7 bit addressing mode actually [7:1] bits of the I2C CR2 register are used but HAL sets the address field as follows:

tmpreg |= (uint32_t)(((uint32_t)DevAddress & I2C_CR2_SADD) | (((uint32_t)Size << 16 ) & I2C_CR2_NBYTES) | \
            (uint32_t)Mode | (uint32_t)Request);

/* update CR2 register */
hi2c->Instance->CR2 = tmpreg;

(I2C_CR2_SADD is 0x3FF which actually just masks the first 10 bits.) So the point is that HAL will set the 7 bit address mistakenly on [6:0] bits of the register if you do not shift to left by one manually.

  • \$\begingroup\$ Thanks, now I can see the mistake! I am receiving garbage ow on the bus, I will try to figure out why \$\endgroup\$ – Vinícius Jean Ferreira Feb 12 '18 at 22:28
  • \$\begingroup\$ @VincíciusJeanFerreira a logic analyzer can be useful also this HAL code is not from the latest version so you should check the actual one in your project. Just to be sure. \$\endgroup\$ – Bence Kaulics Feb 12 '18 at 22:45
  • \$\begingroup\$ Your receive_buffer logic is wrong that is why you see garbage. It is a pointer to nowhere (no memory allocated) yet you try to receive two bytes with it. And then when sending on serial sizeof(receive_buffer) will return the size of the pointer. Define receive_buffer as uint8_t receive_buffer[2] instead. \$\endgroup\$ – Bence Kaulics Feb 12 '18 at 22:55
  • \$\begingroup\$ I post my new code in the comment below \$\endgroup\$ – Vinícius Jean Ferreira Feb 12 '18 at 23:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.