stm32i2cmpu6050

Can Read from I2C, but not Write


I'm developing a mpu6050 library for learning purposes. To do so, I am using an stm32 mcu and I have created functions to read and write to its registers. They are as follows:

static IOStatus_t Stm32f767zi_I2C_Write(uint8_t Address,uint32_t Size,uint8_t* DataPtr)
{

    IOStatus_t Status = IO_SUCCESS;
    HAL_StatusTypeDef HAL_Status;

    uint8_t* WritePointer = (uint8_t*) malloc(Size+1);
    memcpy(WritePointer,&Address,1);
    memcpy(WritePointer+1,DataPtr,Size);

    HAL_Status = HAL_I2C_Master_Transmit(&hi2c2, MPU6050_I2C_ADDRESS<<1, WritePointer, Size+1, 100);

    free(WritePointer);

    if (HAL_Status != HAL_OK)
    {
        Status = IO_FAILURE;
    }
    return Status;
}

static IOStatus_t Stm32f767zi_I2C_Read(uint8_t Address,uint32_t Size,uint8_t* DataPtr)
{
    IOStatus_t Status = IO_SUCCESS;
    HAL_StatusTypeDef HAL_Status;

    HAL_Status = HAL_I2C_Master_Transmit(&hi2c2, MPU6050_I2C_ADDRESS<<1, &Address, 1, 100);
    HAL_Delay(1);
    if (HAL_Status == HAL_OK)
    {
        HAL_Status = HAL_I2C_Master_Receive(&hi2c2, MPU6050_I2C_ADDRESS<<1, DataPtr, Size, 100);
        if (HAL_Status != HAL_OK)
        {
            Status = IO_FAILURE;
        }
    }
    return Status;
}

Then I use this small code to test these functions:

uint8_t RxData;
uint8_t ID;

Stm32f767zi_I2C_Read(REG_WHO_AM_I,1,&ID);
Stm32f767zi_I2C_Write(REG_SAMPLE_RATE_DIVIDER,1,&ID);
Stm32f767zi_I2C_Read(REG_SAMPLE_RATE_DIVIDER,1,&RxData);

Reading the "who am i" register gives me the i2c address of the mpu6050, so I have proved that the reading function works fine. The write to the "sample rate divider" register however doesn't, as when I try to read the value back after having written to it i only get 0x00. I chose this register for writing tests since all its bits are settable. All HAL calls return HAL_OK so I think my requests are being acked by the slave?

What could cause this problem? How come I can read but not write? It's even more strange considering that I use HAL_I2C_Master_Transmit() successfully in the read function. Could the device be locked for writing in some way? I have confirmed that this register is read/write and (among other things) I have tried separating the call to HAL_I2C_Master_Transmit() into two different calls (one for each byte), but nothing seems to work. I have sent the same data through UART to verify that the pointers I use work and they do, so I really don't know what I'm missing here.

The timing diagram for a Single-Byte Write Sequence specified in the reference manual is:

enter image description here enter image description here


Solution

  • Turns out yes, the device was "locked".

    Mpu6050 has a "SLEEP" bit in its "PWR_MGMT_1" register that is set by default and prevents the registers from being written to. Removing this bit before calling Stm32f767zi_I2C_Write(REG_SAMPLE_RATE_DIVIDER,1,&ID); solved the problem for me