[RISC-V MCU 应用开发] 国产risc-v微控制器读取MPU6050

[复制链接]
 楼主| 点赞 发表于 2025-7-27 20:28 | 显示全部楼层 |阅读模式
135456886188548391.png


MPU6050是一个6轴姿态传感器(3轴加速度计和3轴陀螺仪传感器),可以测量芯片自身X、Y、Z轴的加速度、角度参数,通过数据融合,可以得到姿态角。
mpu6050在运动控制、车辆和飞行器控制等方面应用非常的多。


MPU6050作为一个6轴姿态传感器,其中3轴加速度计为x、y、z三个方向的加速度,3轴陀螺仪传感器为围绕x、y、z旋转的加速度。


在MPU6050中,X、Y、Z轴都具有一个加速度计,假设芯片里有6个测力的秤组成一个正方体,正方体内部放一个大小正好的单位质量小球,小球压在一个面上,就会产生对应轴的数据输出。如果压在上面为正值,压在下面为负值,6个面测的力就是3个轴的加速度值。
3392368861a331b769.png


MPU6050芯片内部的陀螺仪测量的实时角速度,分别表示了此时芯片绕X、Y、Z轴旋转的角速度。对角速度进行积分,就可以得到角度。




 楼主| 点赞 发表于 2025-7-27 20:30 | 显示全部楼层
本帖最后由 点赞 于 2025-7-27 20:34 编辑

MPU6050参数:

‌一、加速度计


量程:±2g、±4g、±8g、±16g(默认±2g)。‌‌‌‌
分辨率:16位ADC。‌‌


二、陀螺仪
量程:±250°/s、±500°/s、±1000°/s、±2000°/s(默认±250°/s)。‌‌‌‌
灵敏度误差:±1%。‌‌


三、其他特性

内置温度传感器(用于漂移补偿)。‌‌
数字运动处理器(DMP):支持四元数/欧拉角输出,减轻主控负担。‌‌
采样率:加速度计1kHz,陀螺仪8kHz(DMP融合输出200Hz)。‌‌


‌四、电气特性‌


工作电压:2.375V~3.46V(模块支持3.3V/5V输入)。‌‌

功耗:6轴模式≤3mA,睡眠模式5μA。‌‌

接口:I2C(400kHz,默认地址0x68/0x69),SPI(仅MPU6000支持)









 楼主| 点赞 发表于 2025-7-27 20:43 | 显示全部楼层
电路原理图
5054868861df09d8b0.png

MPU6050 模块内部自带稳压电路,可兼容 3.3V/5V 的供电电压,采用先进的数字滤波技术,提高精度同时抑制了测量噪声。通讯方面,MPU6050 保留了 IIC 接口,高级用户能够采样底层测量数据。值得一提的是,芯片集成了 DMP (Digital Motion Processor)数字动态处理器(以后会用到,实现平衡小车姿体平衡)从陀螺仪、加速度计以及外接的传感器接收并处理数据,处理结果可以从 DMP 寄存器读出,或通过 FIFO(First In First Out) 缓冲。下图为模块的原理图:

8640968861ed88888c.png
 楼主| 点赞 发表于 2025-7-27 20:49 | 显示全部楼层
本帖最后由 点赞 于 2025-7-27 20:52 编辑

HPM5361与MPU6050的连接:

使用的HPM5361开发板P1接口有两组I2C接口,这里使用I2C0接口,及PB03和PB02引脚。
776768861f9a704b8.png


这两个引脚,在开发板上已经有了10K的上拉电阻,使用的mpu6050上也有4.7k的上拉电阻,这里可以共存,不需要特殊处理。
686416886203f1187c.png
 楼主| 点赞 发表于 2025-7-27 20:52 | 显示全部楼层
本帖最后由 点赞 于 2025-7-27 21:16 编辑

工程创建及资源配置:
一、新建工程

打开RT-Thread Studio,在菜单选:文件-->新建-->RT-Thread 项目,在打开的“新建项目”选项卡,填写项目名称,选择“基于开发板”,其他选项默认,点“完成”按钮。

14825688623e84b226.png

二、配置工程资源

双击工程下的“RT-Thread Setting”,打开RT-Thread Setting选项卡。
在软件包项目下,点“添加软件包”,在打开的搜索页面搜索“mpu”,在出现的项目中点“mpu6xxx“软件包的”添加“按钮。

60644688625bb5c465.png
我这里已经添加完毕。
在”软件包“标签页,配置mpu6xxx软件包:
290616886260e07a1a.png

在”组件“标签页打开”使用I2C设备驱动程序“
154066886264e8864f.png
在”硬件“标签页,打开”Enable I2C“选项,并打开I2C0。
540526886269808d9c.png
671356886268f0cbe5.png
 楼主| 点赞 发表于 2025-7-27 20:56 | 显示全部楼层
本帖最后由 点赞 于 2025-7-27 21:34 编辑

主要代码:
mpu6xxx.c文件:
写寄存器:

  1. static rt_err_t mpu6xxx_write_reg(struct mpu6xxx_device *dev, rt_uint8_t reg, rt_uint8_t data)
  2. {
  3.     rt_int8_t res = 0;
  4. #ifdef RT_USING_I2C
  5.     struct rt_i2c_msg msgs;
  6.     rt_uint8_t buf[2] = {reg, data};
  7. #endif
  8.     if (dev->bus->type == RT_Device_Class_I2CBUS)
  9.     {
  10. #ifdef RT_USING_I2C
  11.         msgs.addr  = dev->i2c_addr;    /* slave address */
  12.         msgs.flags = RT_I2C_WR;        /* write flag */
  13.         msgs.buf   = buf;              /* Send data pointer */
  14.         msgs.len   = 2;

  15.         if (rt_i2c_transfer((struct rt_i2c_bus_device *)dev->bus, &msgs, 1) == 1)
  16.         {
  17.             res = RT_EOK;
  18.         }
  19.         else
  20.         {
  21.             res = -RT_ERROR;
  22.         }
  23. #endif
  24.     }
  25.     else
  26.     {
  27. #ifdef RT_USING_SPI
  28.         res = rt_spi_send_then_send((struct rt_spi_device *)dev->bus, ®, 1, &data, 1);
  29. #endif
  30.     }
  31.     return res;
  32. }
读寄存器:

  1. static rt_err_t mpu6xxx_read_regs(struct mpu6xxx_device *dev, rt_uint8_t reg, rt_uint8_t len, rt_uint8_t *buf)
  2. {
  3.     rt_int8_t res = 0;
  4. #ifdef RT_USING_I2C
  5.     struct rt_i2c_msg msgs[2];
  6. #endif
  7. #ifdef RT_USING_SPI
  8.     rt_uint8_t tmp;
  9. #endif
  10.     if (dev->bus->type == RT_Device_Class_I2CBUS)
  11.     {
  12. #ifdef RT_USING_I2C
  13.         msgs[0].addr  = dev->i2c_addr;    /* Slave address */
  14.         msgs[0].flags = RT_I2C_WR;        /* Write flag */
  15.         msgs[0].buf   = ®             /* Slave register address */
  16.         msgs[0].len   = 1;                /* Number of bytes sent */

  17.         msgs[1].addr  = dev->i2c_addr;    /* Slave address */
  18.         msgs[1].flags = RT_I2C_RD;        /* Read flag */
  19.         msgs[1].buf   = buf;              /* Read data pointer */
  20.         msgs[1].len   = len;              /* Number of bytes read */

  21.         if (rt_i2c_transfer((struct rt_i2c_bus_device *)dev->bus, msgs, 2) == 2)
  22.         {
  23.             res = RT_EOK;
  24.         }
  25.         else
  26.         {
  27.             res = -RT_ERROR;
  28.         }
  29. #endif
  30.     }
  31.     else
  32.     {
  33. #ifdef RT_USING_SPI
  34.         //The first bit of the first byte contains the Read/Write bit and indicates the Read (1) or Write (0) operation.
  35.         tmp = reg | 0x80;

  36.         res = rt_spi_send_then_recv((struct rt_spi_device *)dev->bus, &tmp, 1, buf, len);
  37. #endif
  38.     }
  39.     return res;
  40. }
写寄存器的bit位:

  1. static rt_err_t mpu6xxx_write_bit(struct mpu6xxx_device *dev, rt_uint8_t reg, rt_uint8_t bit, rt_uint8_t data)
  2. {
  3.     rt_uint8_t byte;
  4.     rt_err_t res;

  5.     res = mpu6xxx_read_regs(dev, reg, 1, &byte);
  6.     if (res != RT_EOK)
  7.     {
  8.         return res;
  9.     }

  10.     byte = (data != 0) ? (byte | (1 << bit)) : (byte & ~(1 << bit));

  11.     return mpu6xxx_write_reg(dev, reg, byte);
  12. }
读寄存器的bit位:

  1. static rt_err_t mpu6xxx_read_bit(struct mpu6xxx_device *dev, rt_uint8_t reg, rt_uint8_t bit, rt_uint8_t *data)
  2. {
  3.     rt_uint8_t byte;
  4.     rt_err_t res;

  5.     res = mpu6xxx_read_regs(dev, reg, 1, &byte);
  6.     if (res != RT_EOK)
  7.     {
  8.         return res;
  9.     }

  10.     *data = byte & (1 << bit);

  11.     return RT_EOK;
  12. }
写寄存器的多个bit位:

  1. static rt_err_t mpu6xxx_write_bits(struct mpu6xxx_device *dev, rt_uint8_t reg, rt_uint8_t start_bit, rt_uint8_t len, rt_uint8_t data)
  2. {
  3.     rt_uint8_t byte, mask;
  4.     rt_err_t res;

  5.     res = mpu6xxx_read_regs(dev, reg, 1, &byte);
  6.     if (res != RT_EOK)
  7.     {
  8.         return res;
  9.     }

  10.     mask = ((1 << len) - 1) << (start_bit - len + 1);
  11.     data <<= (start_bit - len + 1); // shift data into correct position
  12.     data &= mask; // zero all non-important bits in data
  13.     byte &= ~(mask); // zero all important bits in existing byte
  14.     byte |= data; // combine data with existing byte

  15.     return mpu6xxx_write_reg(dev, reg, byte);
  16. }
读寄存器的多个bit位:

  1. static rt_err_t mpu6xxx_read_bits(struct mpu6xxx_device *dev, rt_uint8_t reg, rt_uint8_t start_bit, rt_uint8_t len, rt_uint8_t *data)
  2. {
  3.     rt_uint8_t byte, mask;
  4.     rt_err_t res;

  5.     res = mpu6xxx_read_regs(dev, reg, 1, &byte);
  6.     if (res != RT_EOK)
  7.     {
  8.         return res;
  9.     }

  10.     mask = ((1 << len) - 1) << (start_bit - len + 1);
  11.     byte &= mask;
  12.     byte >>= (start_bit - len + 1);
  13.     *data = byte;

  14.     return RT_EOK;
  15. }
获取加速度原始数据:

  1. static rt_err_t mpu6xxx_get_accel_raw(struct mpu6xxx_device *dev, struct mpu6xxx_3axes *accel)
  2. {
  3.     rt_uint8_t buffer[6];
  4.     rt_err_t res;

  5.     res = mpu6xxx_read_regs(dev, MPU6XXX_RA_ACCEL_XOUT_H, 6, buffer);
  6.     if (res != RT_EOK)
  7.     {
  8.         return res;
  9.     }

  10.     accel->x = ((rt_uint16_t)buffer[0] << 8) + buffer[1];
  11.     accel->y = ((rt_uint16_t)buffer[2] << 8) + buffer[3];
  12.     accel->z = ((rt_uint16_t)buffer[4] << 8) + buffer[5];

  13.     return RT_EOK;
  14. }
获取陀螺仪原始数据:

  1. static rt_err_t mpu6xxx_get_gyro_raw(struct mpu6xxx_device *dev, struct mpu6xxx_3axes *gyro)
  2. {
  3.     rt_uint8_t buffer[6];
  4.     rt_err_t res;

  5.     res = mpu6xxx_read_regs(dev, MPU6XXX_RA_GYRO_XOUT_H, 6, buffer);
  6.     if (res != RT_EOK)
  7.     {
  8.         return res;
  9.     }

  10.     gyro->x = ((rt_uint16_t)buffer[0] << 8) + buffer[1];
  11.     gyro->y = ((rt_uint16_t)buffer[2] << 8) + buffer[3];
  12.     gyro->z = ((rt_uint16_t)buffer[4] << 8) + buffer[5];

  13.     return RT_EOK;
  14. }
获取mpu6050内部温度传感器原始数据:

  1. static rt_err_t mpu6xxx_get_temp_raw(struct mpu6xxx_device *dev, rt_int16_t *temp)
  2. {
  3.     rt_uint8_t buffer[2];
  4.     rt_err_t res;

  5.     res = mpu6xxx_read_regs(dev, MPU6XXX_RA_TEMP_OUT_H, 2, buffer);
  6.     if (res != RT_EOK)
  7.     {
  8.         return res;
  9.     }

  10.     *temp = ((rt_uint16_t)buffer[0] << 8) + buffer[1];

  11.     return RT_EOK;
  12. }
获取mpu6050的配置参数:

  1. static rt_err_t mpu6xxx_get_param(struct mpu6xxx_device *dev, enum mpu6xxx_cmd cmd, rt_uint16_t *param)
  2. {
  3.     rt_uint8_t data = 0;
  4.     rt_err_t res = RT_EOK;

  5.     RT_ASSERT(dev);

  6.     switch (cmd)
  7.     {
  8.     case MPU6XXX_GYRO_RANGE:  /* Gyroscope full scale range */
  9.         res = mpu6xxx_read_bits(dev, MPU6XXX_RA_GYRO_CONFIG, MPU6XXX_GCONFIG_FS_SEL_BIT, MPU6XXX_GCONFIG_FS_SEL_LENGTH, &data);
  10.         *param = data;
  11.         break;
  12.     case MPU6XXX_ACCEL_RANGE: /* Accelerometer full scale range */
  13.         res = mpu6xxx_read_bits(dev, MPU6XXX_RA_ACCEL_CONFIG, MPU6XXX_ACONFIG_AFS_SEL_BIT, MPU6XXX_ACONFIG_AFS_SEL_LENGTH, &data);
  14.         *param = data;
  15.         break;
  16.     case MPU6XXX_DLPF_CONFIG: /* Digital Low Pass Filter */
  17.         res = mpu6xxx_read_bits(dev, MPU6XXX_RA_CONFIG, MPU6XXX_CFG_DLPF_CFG_BIT, MPU6XXX_CFG_DLPF_CFG_LENGTH, &data);
  18.         *param = data;
  19.         break;
  20.     case MPU6XXX_SAMPLE_RATE: /* Sample Rate */
  21.         /* Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV) */
  22.         res = mpu6xxx_read_bits(dev, MPU6XXX_RA_CONFIG, MPU6XXX_CFG_DLPF_CFG_BIT, MPU6XXX_CFG_DLPF_CFG_LENGTH, &data);
  23.         if (res != RT_EOK)
  24.         {
  25.             break;
  26.         }

  27.         if (data == 0 || data == 7) /* dlpf is disable */
  28.         {
  29.             res = mpu6xxx_read_regs(dev, MPU6XXX_RA_SMPLRT_DIV, 1, &data);
  30.             *param = 8000 / (data + 1);
  31.         }
  32.         else /* dlpf is enable */
  33.         {
  34.             res = mpu6xxx_read_regs(dev, MPU6XXX_RA_SMPLRT_DIV, 1, &data);
  35.             *param = 1000 / (data + 1);
  36.         }
  37.         break;
  38.     case MPU6XXX_SLEEP: /* sleep mode */
  39.         res = mpu6xxx_read_bit(dev, MPU6XXX_RA_PWR_MGMT_1, MPU6XXX_PWR1_SLEEP_BIT, &data);
  40.         *param = data;
  41.         break;
  42.     }

  43.     return res;
  44. }
配置mpu6050参数:

  1. rt_err_t mpu6xxx_set_param(struct mpu6xxx_device *dev, enum mpu6xxx_cmd cmd, rt_uint16_t param)
  2. {
  3.     rt_uint8_t data = 0;
  4.     rt_err_t res = RT_EOK;

  5.     RT_ASSERT(dev);

  6.     switch (cmd)
  7.     {
  8.     case MPU6XXX_GYRO_RANGE:  /* Gyroscope full scale range */
  9.         res = mpu6xxx_write_bits(dev, MPU6XXX_RA_GYRO_CONFIG, MPU6XXX_GCONFIG_FS_SEL_BIT, MPU6XXX_GCONFIG_FS_SEL_LENGTH, param);
  10.         dev->config.gyro_range = param;
  11.         break;
  12.     case MPU6XXX_ACCEL_RANGE: /* Accelerometer full scale range */
  13.         res = mpu6xxx_write_bits(dev, MPU6XXX_RA_ACCEL_CONFIG, MPU6XXX_ACONFIG_AFS_SEL_BIT, MPU6XXX_ACONFIG_AFS_SEL_LENGTH, param);
  14.         dev->config.accel_range = param;
  15.         break;
  16.     case MPU6XXX_DLPF_CONFIG: /* Digital Low Pass Filter */
  17.         res = mpu6xxx_write_bits(dev, MPU6XXX_RA_CONFIG, MPU6XXX_CFG_DLPF_CFG_BIT, MPU6XXX_CFG_DLPF_CFG_LENGTH, param);
  18.         break;
  19.     case MPU6XXX_SAMPLE_RATE: /* Sample Rate = 16-bit unsigned value.
  20.                                  Sample Rate = [1000 -  4]HZ when dlpf is enable
  21.                                  Sample Rate = [8000 - 32]HZ when dlpf is disable */

  22.         //Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV)
  23.         res = mpu6xxx_read_bits(dev, MPU6XXX_RA_CONFIG, MPU6XXX_CFG_DLPF_CFG_BIT, MPU6XXX_CFG_DLPF_CFG_LENGTH, &data);
  24.         if (res != RT_EOK)
  25.         {
  26.             break;
  27.         }

  28.         if (data == 0 || data == 7) /* dlpf is disable */
  29.         {
  30.             if (param > 8000)
  31.                 data = 0;
  32.             else if (param < 32)
  33.                 data = 0xFF;
  34.             else
  35.                 data = 8000 / param - 1;
  36.         }
  37.         else /* dlpf is enable */
  38.         {
  39.             if (param > 1000)
  40.                 data = 0;
  41.             else if (param < 4)
  42.                 data = 0xFF;
  43.             else
  44.                 data = 1000 / param - 1;
  45.         }
  46.         res = mpu6xxx_write_reg(dev, MPU6XXX_RA_SMPLRT_DIV, data);
  47.         break;
  48.     case MPU6XXX_SLEEP: /* Configure sleep mode */
  49.         res = mpu6xxx_write_bit(dev, MPU6XXX_RA_PWR_MGMT_1, MPU6XXX_PWR1_SLEEP_BIT, param);
  50.         break;
  51.     }

  52.     return res;
  53. }
获取加速度值:

  1. rt_err_t mpu6xxx_get_accel(struct mpu6xxx_device *dev, struct mpu6xxx_3axes *accel)
  2. {
  3.     struct mpu6xxx_3axes tmp;
  4.     rt_uint16_t sen;
  5.     rt_err_t res;

  6.     res = mpu6xxx_get_accel_raw(dev, &tmp);
  7.     if (res != RT_EOK)
  8.     {
  9.         return res;
  10.     }

  11.     sen = MPU6XXX_ACCEL_SEN >> dev->config.accel_range;

  12.     accel->x = (rt_int32_t)tmp.x * 1000 / sen;
  13.     accel->y = (rt_int32_t)tmp.y * 1000 / sen;
  14.     accel->z = (rt_int32_t)tmp.z * 1000 / sen;

  15.     return RT_EOK;
  16. }
获取陀螺仪数据:

  1. rt_err_t mpu6xxx_get_gyro(struct mpu6xxx_device *dev, struct mpu6xxx_3axes *gyro)
  2. {
  3.     struct mpu6xxx_3axes tmp;
  4.     rt_uint16_t sen;
  5.     rt_err_t res;

  6.     res = mpu6xxx_get_gyro_raw(dev, &tmp);
  7.     if (res != RT_EOK)
  8.     {
  9.         return res;
  10.     }

  11.     sen = MPU6XXX_GYRO_SEN >> dev->config.gyro_range;

  12.     gyro->x = (rt_int32_t)tmp.x * 100 / sen;
  13.     gyro->y = (rt_int32_t)tmp.y * 100 / sen;
  14.     gyro->z = (rt_int32_t)tmp.z * 100 / sen;

  15.     return RT_EOK;
  16. }
获取温度:

  1. rt_err_t mpu6xxx_get_temp(struct mpu6xxx_device *dev, float *temp)
  2. {
  3.     rt_int16_t tmp;
  4.     rt_err_t res;

  5.     res = mpu6xxx_get_temp_raw(dev, &tmp);
  6.     if (res != RT_EOK)
  7.     {
  8.         return res;
  9.     }

  10.     if (dev->id == MPU6050_WHO_AM_I)
  11.     {
  12.         /* mpu60x0: Temperature in degrees C = (TEMP_OUT Register Value as a signed quantity)/340 + 36.53 */
  13.         *temp = (double)tmp / MPU60X0_TEMP_SEN + MPU60X0_TEMP_OFFSET;
  14.     }
  15.     else
  16.     {
  17.         /* mpu6500:  ((TEMP_OUT - RoomTemp_Offset)/Temp_Sensitivity)+ 21degC */
  18.         *temp = (double)tmp / MPU6500_TEMP_SEN + MPU6500_TEMP_OFFSET;
  19.     }

  20.     return RT_EOK;
  21. }
mpu6050初始化:

  1. struct mpu6xxx_device *mpu6xxx_init(const char *dev_name, rt_uint8_t param)
  2. {
  3.     struct mpu6xxx_device *dev = RT_NULL;
  4.     rt_uint8_t reg = 0xFF, res = RT_EOK;

  5.     RT_ASSERT(dev_name);

  6.     dev = rt_calloc(1, sizeof(struct mpu6xxx_device));
  7.     if (dev == RT_NULL)
  8.     {
  9.         LOG_E("Can't allocate memory for mpu6xxx device on '%s' ", dev_name);
  10.         goto __exit;
  11.     }

  12.     dev->bus = rt_device_find(dev_name);
  13.     if (dev->bus == RT_NULL)
  14.     {
  15.         LOG_E("Can't find device:'%s'", dev_name);
  16.         goto __exit;
  17.     }

  18.     if (dev->bus->type == RT_Device_Class_I2CBUS)
  19.     {
  20.         if (param != RT_NULL)
  21.         {
  22.             dev->i2c_addr = param;
  23.         }
  24.         else
  25.         {
  26.             /* find mpu6xxx device at address: 0x68 */
  27.             dev->i2c_addr = MPU6XXX_ADDRESS_AD0_LOW;
  28.             if (mpu6xxx_read_regs(dev, MPU6XXX_RA_WHO_AM_I, 1, ®) != RT_EOK)
  29.             {
  30.                 /* find mpu6xxx device at address 0x69 */
  31.                 dev->i2c_addr = MPU6XXX_ADDRESS_AD0_HIGH;
  32.                 if (mpu6xxx_read_regs(dev, MPU6XXX_RA_WHO_AM_I, 1, ®) != RT_EOK)
  33.                 {
  34.                     LOG_E("Can't find device at '%s'!", dev_name);
  35.                     goto __exit;
  36.                 }
  37.             }
  38.             LOG_D("Device i2c address is:'0x%x'!", dev->i2c_addr);
  39.         }
  40.     }
  41.     else if (dev->bus->type == RT_Device_Class_SPIDevice)
  42.     {
  43. #ifdef RT_USING_SPI
  44.         struct rt_spi_configuration cfg;

  45.         cfg.data_width = 8;
  46.         cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;
  47.         cfg.max_hz = MPU60X0_SPI_MAX_SPEED; /* Set spi max speed */

  48.         rt_spi_configure((struct rt_spi_device *)dev->bus, &cfg);
  49. #endif
  50.     }
  51.     else
  52.     {
  53.         LOG_E("Unsupported device:'%s'!", dev_name);
  54.         goto __exit;
  55.     }

  56.     if (mpu6xxx_read_regs(dev, MPU6XXX_RA_WHO_AM_I, 1, ®) != RT_EOK)
  57.     {
  58.         LOG_E("Failed to read device id!");
  59.         goto __exit;
  60.     }

  61.     dev->id = reg;

  62.     switch (dev->id)
  63.     {
  64.     case MPU6050_WHO_AM_I:
  65.         LOG_I("Find device: mpu6050!");
  66.         break;
  67.     case MPU6500_WHO_AM_I:
  68.         LOG_I("Find device: mpu6500!");
  69.         break;
  70.     case MPU9250_WHO_AM_I:
  71.         LOG_I("Find device: mpu9250!");
  72.         break;
  73.     case ICM20608G_WHO_AM_I:
  74.     case ICM20608D_WHO_AM_I:
  75.         LOG_I("Find device: icm20608!");
  76.         break;
  77.     case 0xFF:
  78.         LOG_E("No device connection!");
  79.         goto __exit;
  80.     default:
  81.         LOG_W("Unknown device id: 0x%x!", reg);
  82.     }

  83.     res += mpu6xxx_get_param(dev, MPU6XXX_ACCEL_RANGE, &dev->config.accel_range);
  84.     res += mpu6xxx_get_param(dev, MPU6XXX_GYRO_RANGE, &dev->config.gyro_range);

  85.     res += mpu6xxx_write_bits(dev, MPU6XXX_RA_PWR_MGMT_1, MPU6XXX_PWR1_CLKSEL_BIT, MPU6XXX_PWR1_CLKSEL_LENGTH, MPU6XXX_CLOCK_PLL_XGYRO);
  86.     res += mpu6xxx_set_param(dev, MPU6XXX_GYRO_RANGE, MPU6XXX_GYRO_RANGE_250DPS);
  87.     res += mpu6xxx_set_param(dev, MPU6XXX_ACCEL_RANGE, MPU6XXX_ACCEL_RANGE_2G);
  88.     res += mpu6xxx_set_param(dev, MPU6XXX_SLEEP, MPU6XXX_SLEEP_DISABLE);

  89. #ifdef PKG_USING_MPU6XXX_MAG
  90.     mpu6xxx_write_reg(dev, MPU6XXX_RA_USER_CTRL, 0x20);
  91.     mpu92_mag_write_reg(dev, AK8963_REG_CNTL2, 0x01);      /* [0]  Reset Device                  */
  92.     rt_thread_mdelay(1);
  93.     mpu92_mag_write_reg(dev, AK8963_REG_CNTL1, 0x00);      /* [1]  Power-down mode               */
  94.     mpu92_mag_write_reg(dev, AK8963_REG_CNTL1, 0x0F);      /* [2]  Fuse ROM access mode          */
  95.     mpu92_mag_write_reg(dev, AK8963_REG_CNTL1, 0x00);      /* [3]  Power-down mode               */
  96.     rt_thread_mdelay(1);    // 100us
  97.     mpu92_mag_write_reg(dev, AK8963_REG_CNTL1, 0x16);      /* [4]  16bits and Continuous measurement mode 2 */

  98.     /* config mpu9250 i2c */
  99.     rt_thread_mdelay(2);
  100.     mpu6xxx_write_reg(dev, MPU6XXX_RA_I2C_MST_CTRL, 0x5D);
  101.     rt_thread_mdelay(2);
  102.     mpu6xxx_write_reg(dev, MPU6XXX_RA_I2C_SLV0_ADDR, AK8963_I2C_ADDR | 0x80);
  103.     rt_thread_mdelay(2);
  104.     mpu6xxx_write_reg(dev, MPU6XXX_RA_I2C_SLV0_REG, AK8963_REG_ST1);
  105.     rt_thread_mdelay(2);
  106.     mpu6xxx_write_reg(dev, MPU6XXX_RA_I2C_SLV0_CTRL, MPU6500_I2C_SLVx_EN | 8);
  107.     rt_thread_mdelay(2);
  108.     mpu6xxx_write_reg(dev, MPU6XXX_RA_I2C_SLV4_CTRL, 0x09);
  109.     rt_thread_mdelay(2);
  110.     mpu6xxx_write_reg(dev, MPU6XXX_RA_I2C_MST_DELAY_CTRL, 0x81);
  111. #endif

  112.     if (res == RT_EOK)
  113.     {
  114.         LOG_I("Device init succeed!");
  115.     }
  116.     else
  117.     {
  118.         LOG_W("Error in device initialization!");
  119.     }
  120.     return dev;

  121. __exit:
  122.     if (dev != RT_NULL)
  123.     {
  124.         rt_free(dev);
  125.     }
  126.     return RT_NULL;
  127. }


 楼主| 点赞 发表于 2025-7-27 21:36 | 显示全部楼层
效果验证:
在串口调试工具,输入:
 楼主| 点赞 发表于 2025-7-27 21:50 | 显示全部楼层
效果验证:
在串口调试工具,输入:
  1. mpu6xxx_test
会打印mpu6050的加速度和陀螺仪数据如下:

3136868862bbe2bf6d.png
ShimmeringDawn 发表于 2025-7-28 11:37 | 显示全部楼层
老哥求例程
fanzq2005 发表于 2025-7-28 19:38 | 显示全部楼层
谢谢分享,大家一起进步~!谢谢分享,大家一起进步~!
魔法森林精灵 发表于 2025-8-1 12:00 | 显示全部楼层
MPU6050的数据融合技术确实在很多领域都有应用,特别是在需要精确姿态控制的场合。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

20

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部