如何使用STM32F4从MPU6050读取数据

如何使用STM32F4从MPU6050读取数据,stm32,i2c,stm32f4,mpu6050,Stm32,I2c,Stm32f4,Mpu6050,我需要监视一个物体的倾斜。我使用的是MPU6050加速度计、陀螺仪和控制器STM32F401RBT6。下面的代码是我正在使用的解决方案 #define MPU6050_ADDR 0xD0 #define SMPLRT_DIV_REG 0x19 #define GYRO_CONFIG_REG 0x1B #define ACCEL_CONFIG_REG 0x1C #define ACCEL_XOUT_H_REG 0x3B #define TEMP_OUT_H_REG 0x41 #define GYR

我需要监视一个物体的倾斜。我使用的是MPU6050加速度计、陀螺仪和控制器STM32F401RBT6。下面的代码是我正在使用的解决方案

#define MPU6050_ADDR 0xD0
#define SMPLRT_DIV_REG 0x19
#define GYRO_CONFIG_REG 0x1B
#define ACCEL_CONFIG_REG 0x1C
#define ACCEL_XOUT_H_REG 0x3B
#define TEMP_OUT_H_REG 0x41
#define GYRO_XOUT_H_REG 0x43
#define PWR_MGMT_1_REG 0x6B
#define WHO_AM_I_REG 0X75

uint16_t Accel_X_RAW,Accel_Y_RAW,Accel_Z_RAW;
uint16_t Ax,Ay,Az;
char buffer[10];

void MPU6050_Init(void)
{
    uint8_t check, data;
    HAL_I2C_Mem_Read(&hi2c3,MPU6050_ADDR,WHO_AM_I_REG,1,&check,1,100);
    if(check == 104)
    {
        data = 0x07;
        HAL_I2C_Mem_Write(&hi2c3,MPU6050_ADDR,SMPLRT_DIV_REG,1,&data,1,50);
        HAL_Delay(50);
        data = 0x00;
        HAL_I2C_Mem_Write(&hi2c3,MPU6050_ADDR,ACCEL_CONFIG_REG,1,&data,1,50);
        HAL_Delay(50);
        data = 0x00;
        HAL_I2C_Mem_Write(&hi2c3,MPU6050_ADDR,GYRO_CONFIG_REG,1,&data,1,50);
        HAL_Delay(50);
        data = 0;
        HAL_I2C_Mem_Write(&hi2c3,MPU6050_ADDR,PWR_MGMT_1_REG,1,&data,1,50);
        HAL_Delay(50);
    }
}

void MPU6050_Read_Accel(void)
{
    uint8_t recData[6];
    for(int i=0;i<6;i++) recData[i] = 0;

    HAL_I2C_Mem_Read(&hi2c3,MPU6050_ADDR,ACCEL_XOUT_H_REG,I2C_MEMADD_SIZE_8BIT,recData,6,100);
    HAL_Delay(50);
    uint16_t dataConvert1,dataConvert2;
    dataConvert1 = (uint16_t)(0x0000 | recData[0]) << 8;
    dataConvert2 = (uint16_t)(0x0000 | recData[1]);
    Accel_X_RAW = dataConvert1 | dataConvert2;
    dataConvert1 = (uint16_t)(0x0000 | recData[2]) << 8;
    dataConvert2 = (uint16_t)(0x0000 | recData[3]);
    Accel_Y_RAW = dataConvert1 | dataConvert2;
    dataConvert1 = (uint16_t)(0x0000 | recData[4]) << 8;
    dataConvert2 = (uint16_t)(0x0000 | recData[5]);
    Accel_Z_RAW = dataConvert1 | dataConvert2;

    Ax = (uint16_t)(Accel_X_RAW / 16384);
    Ay = (uint16_t)(Accel_Y_RAW / 16384);
    Az = (uint16_t)(Accel_Z_RAW / 16384);
}

int main(void)
{
    HAL_Init();

    SystemClock_Config();

    MX_I2C3_Init();
    MX_GPIO_Init();
    MX_USB_DEVICE_Init();

    MPU6050_Init();

    while (1)
    {
      MPU6050_Read_Accel();
      sprintf(buffer, "%d / ", Accel_X_RAW);
      CDC_Transmit_FS((char*)buffer,10);
    }
}
我已经在ATMEL控制器Arduino上完成了,它工作了,但在STM32上没有。
我正在尝试读取X轴的值,并使用USB CDC显示它。此代码将“Accel_X_RAW”变量的值设置为0到65535之间。在Arduino中,当对象停止时,参考值为32768,但如果没有移动,则使用STM32的读取将保持在最大值65535。我不知道这段代码出了什么问题,我尝试了很多选择,但仍然不起作用。您能帮助我吗。

根据MPU6050数据表,加速度和陀螺仪的16位值以带符号的2的补码形式返回,它检测+-g范围内的加速度值。当您在无符号变量中接收有符号数据时,结果不是您所期望的。因此,将所有uint16数据类型替换为int16

您获得65535值的原因;有符号int16形式中-1的十六进制值为0xFFFF。但是,如果将其存储在uint16_t变量中,它将被读取为65535。我假设静止时的默认加速度值为-1g

#include <stdlib.h> /* For using memset */

#define MPU6050_ADDR 0xD0
#define SMPLRT_DIV_REG 0x19
#define GYRO_CONFIG_REG 0x1B
#define ACCEL_CONFIG_REG 0x1C
#define ACCEL_XOUT_H_REG 0x3B
#define TEMP_OUT_H_REG 0x41
#define GYRO_XOUT_H_REG 0x43
#define PWR_MGMT_1_REG 0x6B
#define WHO_AM_I_REG 0X75

int16_t Accel_X_RAW,Accel_Y_RAW,Accel_Z_RAW;
int16_t Ax,Ay,Az;
char buffer[10];

void MPU6050_Init(void)
{
    uint8_t check, data;
    HAL_I2C_Mem_Read(&hi2c3,MPU6050_ADDR,WHO_AM_I_REG,1,&check,1,100);
    if(check == 104)
    {
        data = 0x07;
        HAL_I2C_Mem_Write(&hi2c3,MPU6050_ADDR,SMPLRT_DIV_REG,1,&data,1,50);
        HAL_Delay(50);
        data = 0x00;
        HAL_I2C_Mem_Write(&hi2c3,MPU6050_ADDR,ACCEL_CONFIG_REG,1,&data,1,50);
        HAL_Delay(50);
        data = 0x00;
        HAL_I2C_Mem_Write(&hi2c3,MPU6050_ADDR,GYRO_CONFIG_REG,1,&data,1,50);
        HAL_Delay(50);
        data = 0;
        HAL_I2C_Mem_Write(&hi2c3,MPU6050_ADDR,PWR_MGMT_1_REG,1,&data,1,50);
        HAL_Delay(50);
    }
}

void MPU6050_Read_Accel(void)
{
    uint8_t recData[6];
    //for(int i=0;i<6;i++) recData[i] = 0;
    memset(recData, 0, sizeof(recData));

    HAL_I2C_Mem_Read(&hi2c3,MPU6050_ADDR,ACCEL_XOUT_H_REG,I2C_MEMADD_SIZE_8BIT,recData,6,100);
    HAL_Delay(50);

    Accel_X_RAW = (int16_t)(recData[0] << 8 | recData[1]);
    Accel_Y_RAW = (int16_t)(recData[2] << 8 | recData[3]);
    Accel_Z_RAW = (int16_t)(recData[4] << 8 | recData[5]);

    Ax = (int16_t)(Accel_X_RAW / 16384);
    Ay = (int16_t)(Accel_Y_RAW / 16384);
    Az = (int16_t)(Accel_Z_RAW / 16384);
}

int main(void)
{
    HAL_Init();

    SystemClock_Config();

    MX_I2C3_Init();
    MX_GPIO_Init();
    MX_USB_DEVICE_Init();

    MPU6050_Init();

    while (1)
    {
      MPU6050_Read_Accel();
      sprintf(buffer, "%d / ", Accel_X_RAW);
      CDC_Transmit_FS((char*)buffer,10);
    }
}

根据MPU6050数据表,加速度和陀螺仪的16位值以带符号的2的补码形式返回,它检测+-g范围内的加速度值。当您在无符号变量中接收有符号数据时,结果不是您所期望的。因此,将所有uint16数据类型替换为int16

您获得65535值的原因;有符号int16形式中-1的十六进制值为0xFFFF。但是,如果将其存储在uint16_t变量中,它将被读取为65535。我假设静止时的默认加速度值为-1g

#include <stdlib.h> /* For using memset */

#define MPU6050_ADDR 0xD0
#define SMPLRT_DIV_REG 0x19
#define GYRO_CONFIG_REG 0x1B
#define ACCEL_CONFIG_REG 0x1C
#define ACCEL_XOUT_H_REG 0x3B
#define TEMP_OUT_H_REG 0x41
#define GYRO_XOUT_H_REG 0x43
#define PWR_MGMT_1_REG 0x6B
#define WHO_AM_I_REG 0X75

int16_t Accel_X_RAW,Accel_Y_RAW,Accel_Z_RAW;
int16_t Ax,Ay,Az;
char buffer[10];

void MPU6050_Init(void)
{
    uint8_t check, data;
    HAL_I2C_Mem_Read(&hi2c3,MPU6050_ADDR,WHO_AM_I_REG,1,&check,1,100);
    if(check == 104)
    {
        data = 0x07;
        HAL_I2C_Mem_Write(&hi2c3,MPU6050_ADDR,SMPLRT_DIV_REG,1,&data,1,50);
        HAL_Delay(50);
        data = 0x00;
        HAL_I2C_Mem_Write(&hi2c3,MPU6050_ADDR,ACCEL_CONFIG_REG,1,&data,1,50);
        HAL_Delay(50);
        data = 0x00;
        HAL_I2C_Mem_Write(&hi2c3,MPU6050_ADDR,GYRO_CONFIG_REG,1,&data,1,50);
        HAL_Delay(50);
        data = 0;
        HAL_I2C_Mem_Write(&hi2c3,MPU6050_ADDR,PWR_MGMT_1_REG,1,&data,1,50);
        HAL_Delay(50);
    }
}

void MPU6050_Read_Accel(void)
{
    uint8_t recData[6];
    //for(int i=0;i<6;i++) recData[i] = 0;
    memset(recData, 0, sizeof(recData));

    HAL_I2C_Mem_Read(&hi2c3,MPU6050_ADDR,ACCEL_XOUT_H_REG,I2C_MEMADD_SIZE_8BIT,recData,6,100);
    HAL_Delay(50);

    Accel_X_RAW = (int16_t)(recData[0] << 8 | recData[1]);
    Accel_Y_RAW = (int16_t)(recData[2] << 8 | recData[3]);
    Accel_Z_RAW = (int16_t)(recData[4] << 8 | recData[5]);

    Ax = (int16_t)(Accel_X_RAW / 16384);
    Ay = (int16_t)(Accel_Y_RAW / 16384);
    Az = (int16_t)(Accel_Z_RAW / 16384);
}

int main(void)
{
    HAL_Init();

    SystemClock_Config();

    MX_I2C3_Init();
    MX_GPIO_Init();
    MX_USB_DEVICE_Init();

    MPU6050_Init();

    while (1)
    {
      MPU6050_Read_Accel();
      sprintf(buffer, "%d / ", Accel_X_RAW);
      CDC_Transmit_FS((char*)buffer,10);
    }
}