RT-Thread Studio学习(十)MPU9250
RT-Thread Studio学习(十)MPU9250
- 简介
- 新建RT-Thread项目并使用外部时钟
- 设置MPU9250的驱动框架
- 驱动代码的移植
- 测试
- 总结
简介
本文将基于STM32F407VET芯片介绍如何在RT-Thread Studio开发环境下运用9轴传感器MPU9250。
新建RT-Thread项目并使用外部时钟
详细步骤参考文档《RT-Thread Studio学习(一)使用外部时钟系统》。
设置MPU9250的驱动框架
RT-Thread Studio设置
使能如下组件并进行配置:

board.h文件中使能I2C1:

驱动代码的移植
参考正点原子阿波罗F429的MPU9250实验,进行了相应的移植。
首先是直接移植mpu9250.h和mpu9250.c文件,修改为app_mpu9250.h和app_mpu9250.c。
app_mpu9250.h代码如下:
/** Copyright (c) 2006-2021, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author Notes* 2021-06-20 Administrator the first version*/
#ifndef APPLICATIONS_APP_MPU9250_H_
#define APPLICATIONS_APP_MPU9250_H_#include
#include
#include #include "drv_soft_i2c.h"//如果AD0脚(9脚)接地,IIC地址为0X68(不包含最低位).
//如果接V3.3,则IIC地址为0X69(不包含最低位).
#define MPU9250_ADDR 0X68 //MPU6500的器件IIC地址
#define MPU6500_ID 0X71 //MPU6500的器件ID//MPU9250内部封装了一个AK8963磁力计,地址和ID如下:
#define AK8963_ADDR 0X0C //AK8963的I2C地址
#define AK8963_ID 0X48 //AK8963的器件ID//AK8963的内部寄存器
#define MAG_WIA 0x00 //AK8963的器件ID寄存器地址
#define MAG_CNTL1 0X0A
#define MAG_CNTL2 0X0B#define MAG_XOUT_L 0X03
#define MAG_XOUT_H 0X04
#define MAG_YOUT_L 0X05
#define MAG_YOUT_H 0X06
#define MAG_ZOUT_L 0X07
#define MAG_ZOUT_H 0X08//MPU6500的内部寄存器
#define MPU_SELF_TESTX_REG 0X0D //自检寄存器X
#define MPU_SELF_TESTY_REG 0X0E //自检寄存器Y
#define MPU_SELF_TESTZ_REG 0X0F //自检寄存器Z
#define MPU_SELF_TESTA_REG 0X10 //自检寄存器A
#define MPU_SAMPLE_RATE_REG 0X19 //采样频率分频器
#define MPU_CFG_REG 0X1A //配置寄存器
#define MPU_GYRO_CFG_REG 0X1B //陀螺仪配置寄存器
#define MPU_ACCEL_CFG_REG 0X1C //加速度计配置寄存器
#define MPU_MOTION_DET_REG 0X1F //运动检测阀值设置寄存器
#define MPU_FIFO_EN_REG 0X23 //FIFO使能寄存器
#define MPU_I2CMST_CTRL_REG 0X24 //IIC主机控制寄存器
#define MPU_I2CSLV0_ADDR_REG 0X25 //IIC从机0器件地址寄存器
#define MPU_I2CSLV0_REG 0X26 //IIC从机0数据地址寄存器
#define MPU_I2CSLV0_CTRL_REG 0X27 //IIC从机0控制寄存器
#define MPU_I2CSLV1_ADDR_REG 0X28 //IIC从机1器件地址寄存器
#define MPU_I2CSLV1_REG 0X29 //IIC从机1数据地址寄存器
#define MPU_I2CSLV1_CTRL_REG 0X2A //IIC从机1控制寄存器
#define MPU_I2CSLV2_ADDR_REG 0X2B //IIC从机2器件地址寄存器
#define MPU_I2CSLV2_REG 0X2C //IIC从机2数据地址寄存器
#define MPU_I2CSLV2_CTRL_REG 0X2D //IIC从机2控制寄存器
#define MPU_I2CSLV3_ADDR_REG 0X2E //IIC从机3器件地址寄存器
#define MPU_I2CSLV3_REG 0X2F //IIC从机3数据地址寄存器
#define MPU_I2CSLV3_CTRL_REG 0X30 //IIC从机3控制寄存器
#define MPU_I2CSLV4_ADDR_REG 0X31 //IIC从机4器件地址寄存器
#define MPU_I2CSLV4_REG 0X32 //IIC从机4数据地址寄存器
#define MPU_I2CSLV4_DO_REG 0X33 //IIC从机4写数据寄存器
#define MPU_I2CSLV4_CTRL_REG 0X34 //IIC从机4控制寄存器
#define MPU_I2CSLV4_DI_REG 0X35 //IIC从机4读数据寄存器#define MPU_I2CMST_STA_REG 0X36 //IIC主机状态寄存器
#define MPU_INTBP_CFG_REG 0X37 //中断/旁路设置寄存器
#define MPU_INT_EN_REG 0X38 //中断使能寄存器
#define MPU_INT_STA_REG 0X3A //中断状态寄存器#define MPU_ACCEL_XOUTH_REG 0X3B //加速度值,X轴高8位寄存器
#define MPU_ACCEL_XOUTL_REG 0X3C //加速度值,X轴低8位寄存器
#define MPU_ACCEL_YOUTH_REG 0X3D //加速度值,Y轴高8位寄存器
#define MPU_ACCEL_YOUTL_REG 0X3E //加速度值,Y轴低8位寄存器
#define MPU_ACCEL_ZOUTH_REG 0X3F //加速度值,Z轴高8位寄存器
#define MPU_ACCEL_ZOUTL_REG 0X40 //加速度值,Z轴低8位寄存器#define MPU_TEMP_OUTH_REG 0X41 //温度值高八位寄存器
#define MPU_TEMP_OUTL_REG 0X42 //温度值低8位寄存器#define MPU_GYRO_XOUTH_REG 0X43 //陀螺仪值,X轴高8位寄存器
#define MPU_GYRO_XOUTL_REG 0X44 //陀螺仪值,X轴低8位寄存器
#define MPU_GYRO_YOUTH_REG 0X45 //陀螺仪值,Y轴高8位寄存器
#define MPU_GYRO_YOUTL_REG 0X46 //陀螺仪值,Y轴低8位寄存器
#define MPU_GYRO_ZOUTH_REG 0X47 //陀螺仪值,Z轴高8位寄存器
#define MPU_GYRO_ZOUTL_REG 0X48 //陀螺仪值,Z轴低8位寄存器#define MPU_I2CSLV0_DO_REG 0X63 //IIC从机0数据寄存器
#define MPU_I2CSLV1_DO_REG 0X64 //IIC从机1数据寄存器
#define MPU_I2CSLV2_DO_REG 0X65 //IIC从机2数据寄存器
#define MPU_I2CSLV3_DO_REG 0X66 //IIC从机3数据寄存器#define MPU_I2CMST_DELAY_REG 0X67 //IIC主机延时管理寄存器
#define MPU_SIGPATH_RST_REG 0X68 //信号通道复位寄存器
#define MPU_MDETECT_CTRL_REG 0X69 //运动检测控制寄存器
#define MPU_USER_CTRL_REG 0X6A //用户控制寄存器
#define MPU_PWR_MGMT1_REG 0X6B //电源管理寄存器1
#define MPU_PWR_MGMT2_REG 0X6C //电源管理寄存器2
#define MPU_FIFO_CNTH_REG 0X72 //FIFO计数寄存器高八位
#define MPU_FIFO_CNTL_REG 0X73 //FIFO计数寄存器低八位
#define MPU_FIFO_RW_REG 0X74 //FIFO读写寄存器
#define MPU_DEVICE_ID_REG 0X75 //器件ID寄存器int mpu9250_init(void);
rt_err_t mpu9250_write_reg(rt_uint8_t reg,rt_uint8_t data);
rt_err_t mpu9250_read_reg(rt_uint8_t reg,rt_uint8_t *data);
rt_err_t mpu9250_read_regs(rt_uint8_t reg,rt_uint8_t len,rt_uint8_t *buf);//rt_err_t mpu9250_set_gyro_fsr(rt_uint8_t fsr);//
rt_err_t mpu9250_set_accel_fsr(rt_uint8_t fsr);//
rt_err_t mpu9250_set_lpf(rt_uint16_t lpf);//
rt_err_t mpu9250_set_sample_rate(rt_uint16_t rate);//rt_err_t mpu9250_get_temperature(rt_int16_t *temperature);//
rt_err_t mpu9250_get_gyroscope(rt_int16_t *gx,rt_int16_t *gy,rt_int16_t *gz);//
rt_err_t mpu9250_get_accelerometer(rt_int16_t *ax,rt_int16_t *ay,rt_int16_t *az);//
rt_err_t mpu9250_get_magnetometer(rt_int16_t *mx,rt_int16_t *my,rt_int16_t *mz);//rt_err_t mpu_dmp_write_Len(rt_uint8_t addr,rt_uint8_t reg,rt_uint8_t len,rt_uint8_t *date);//mpu_dmp 移植使用
rt_err_t mpu_dmp_read_Len(rt_uint8_t addr,rt_uint8_t reg,rt_uint8_t len,rt_uint8_t *buf);//mpu_dmp 移植使用static void mpu9250_sample();#endif /* APPLICATIONS_APP_MPU9250_H_ */
app_mpu9250.c代码如下:
/** Copyright (c) 2006-2021, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author Notes* 2021-06-20 Administrator the first version*/
#include
#include #include "app_mpu9250.h"
#include "drv_soft_i2c.h"
//#include "inv_mpu_dmp_motion_driver.h"
//#include "inv_mpu.h"#define MPU9250_I2CBUS_NAME "i2c1"#if 1
#define MPUDEBUG rt_kprintf
#else
#define MPUDEBUG(...)
#endifstatic struct rt_i2c_bus_device *mpu9250_i2c_bus;rt_err_t mpu_dmp_write_Len(rt_uint8_t addr, rt_uint8_t reg, rt_uint8_t len, rt_uint8_t *date) //mpu_dmp 移植使用
{rt_uint8_t buf[len + 1];rt_uint8_t i;buf[0] = reg;for (i = 0; i < len; i++){buf[i + 1] = date[i];}if (rt_i2c_master_send(mpu9250_i2c_bus, addr, 0, buf, len + 1) == len + 1)return RT_EOK;elsereturn -RT_ERROR;
}rt_err_t mpu_dmp_read_Len(rt_uint8_t addr, rt_uint8_t reg, rt_uint8_t len, rt_uint8_t *buf) //mpu_dmp 移植使用
{struct rt_i2c_msg msgs[2];msgs[0].addr = addr;msgs[0].flags = RT_I2C_WR;msgs[0].buf = ®msgs[0].len = 1;msgs[1].addr = addr;msgs[1].flags = RT_I2C_RD;msgs[1].buf = buf;msgs[1].len = len;if (rt_i2c_transfer(mpu9250_i2c_bus, msgs, 2) == 2)return RT_EOK;elsereturn -RT_ERROR;
}//reg:寄存器地址
//data:数据
//返回值:0,正常
// -1,错误代码
rt_err_t mpu9250_write_reg(rt_uint8_t reg, rt_uint8_t data)
{rt_uint8_t buf[2];buf[0] = reg;buf[1] = data;if (rt_i2c_master_send(mpu9250_i2c_bus, MPU9250_ADDR, 0, buf, 2) == 2)return RT_EOK;elsereturn -RT_ERROR;
}
rt_err_t mpu9250_write_magnetometer_reg(rt_uint8_t reg, rt_uint8_t data)
{rt_uint8_t buf[2];buf[0] = reg;buf[1] = data;if (rt_i2c_master_send(mpu9250_i2c_bus, AK8963_ADDR, 0, buf, 2) == 2)return RT_EOK;elsereturn -RT_ERROR;
}
//reg:寄存器地址
//data:数据指针
//返回值:0,正常
// -1,错误代码
rt_err_t mpu9250_read_reg(rt_uint8_t reg, rt_uint8_t *data)
{struct rt_i2c_msg msgs[2];msgs[0].addr = MPU9250_ADDR;msgs[0].flags = RT_I2C_WR;msgs[0].buf = ®msgs[0].len = 1;msgs[1].addr = MPU9250_ADDR;msgs[1].flags = RT_I2C_RD;msgs[1].buf = data;msgs[1].len = 1;if (rt_i2c_transfer(mpu9250_i2c_bus, msgs, 2) == 2)return RT_EOK;elsereturn -RT_ERROR;
}
rt_err_t mpu9250_read_regs(rt_uint8_t reg, rt_uint8_t len, rt_uint8_t *buf)
{struct rt_i2c_msg msgs[2];msgs[0].addr = MPU9250_ADDR;msgs[0].flags = RT_I2C_WR;msgs[0].buf = ®msgs[0].len = 1;msgs[1].addr = MPU9250_ADDR;msgs[1].flags = RT_I2C_RD;msgs[1].buf = buf;msgs[1].len = len;if (rt_i2c_transfer(mpu9250_i2c_bus, msgs, 2) == 2){return RT_EOK;}else{return -RT_ERROR;}
}rt_err_t mpu9250_read_magnetometer_regs(rt_uint8_t reg, rt_uint8_t len, rt_uint8_t *buf)
{struct rt_i2c_msg msgs[2];msgs[0].addr = AK8963_ADDR;msgs[0].flags = RT_I2C_WR;msgs[0].buf = ®msgs[0].len = 1;msgs[1].addr = AK8963_ADDR;msgs[1].flags = RT_I2C_RD;msgs[1].buf = buf;msgs[1].len = len;if (rt_i2c_transfer(mpu9250_i2c_bus, msgs, 2) == 2){return RT_EOK;}else{return -RT_ERROR;}
}rt_err_t mpu9250_read_magnetometer_reg(rt_uint8_t reg, rt_uint8_t *data)
{struct rt_i2c_msg msgs[2];msgs[0].addr = AK8963_ADDR;msgs[0].flags = RT_I2C_WR;msgs[0].buf = ®msgs[0].len = 1;msgs[1].addr = AK8963_ADDR;msgs[1].flags = RT_I2C_RD;msgs[1].buf = data;msgs[1].len = 1;if (rt_i2c_transfer(mpu9250_i2c_bus, msgs, 2) == 2)return RT_EOK;elsereturn -RT_ERROR;
}//#include "inv_mpu_dmp_motion_driver.h"
//设置MPU6050陀螺仪传感器满量程范围
//fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
//返回值:0,设置成功
// -1,设置失败
rt_err_t mpu9250_set_gyro_fsr(rt_uint8_t fsr)
{return mpu9250_write_reg(MPU_GYRO_CFG_REG, fsr << 3); //设置陀螺仪满量程范围
}
//设置MPU6050加速度传感器满量程范围
//fsr:0,±2g;1,±4g;2,±8g;3,±16g
//返回值:0,设置成功
// -1,设置失败
rt_err_t mpu9250_set_accel_fsr(rt_uint8_t fsr)
{return mpu9250_write_reg(MPU_ACCEL_CFG_REG, fsr << 3); //设置加速度传感器满量程范围
}
//设置MPU9250的数字低通滤波器
//lpf:数字低通滤波频率(Hz)
//返回值:0,设置成功
// 其他,设置失败
rt_err_t mpu9250_set_lpf(rt_uint16_t lpf)
{rt_uint8_t data = 0;if (lpf >= 188)data = 1;else if (lpf >= 98)data = 2;else if (lpf >= 42)data = 3;else if (lpf >= 20)data = 4;else if (lpf >= 10)data = 5;else data = 6;return mpu9250_write_reg(MPU_CFG_REG, data); //设置数字低通滤波器
}
//设置MPU6050的采样率(假定Fs=1KHz)
//rate:4~1000(Hz)
//返回值:0,设置成功
// -1,设置失败
rt_err_t mpu9250_set_sample_rate(rt_uint16_t rate)
{rt_uint8_t data;if (rate > 1000)rate = 1000;if (rate < 4)rate = 4;data = 1000 / rate - 1;data = mpu9250_write_reg(MPU_SAMPLE_RATE_REG, data); //设置数字低通滤波器return mpu9250_set_lpf(rate / 2); //自动设置LPF为采样率的一半
}
//rt_err_t MPU9250_write_len(rt_uint8_t addr,rt_uint8_t reg,rt_uint8_t len,rt_uint8_t *buf);
//rt_err_t MPU9250_read_len(rt_uint8_t addr,rt_uint8_t reg,rt_uint8_t len,rt_uint8_t *buf);//得到温度值
//temperature:温度值(扩大了100倍)
//返回值:0,成功
// -1,失败
rt_err_t mpu9250_get_temperature(rt_int16_t *temperature)
{rt_uint8_t buf[2];rt_int16_t raw;float temp;rt_err_t ret;ret = mpu9250_read_regs(MPU_TEMP_OUTH_REG, 2, buf);if (ret == RT_EOK){raw = ((rt_uint16_t)buf[0] << 8) | buf[1];temp = 21 + ((double)raw) / 333.87;*temperature = temp * 100;return RT_EOK;}else{return -RT_ERROR;}
}
rt_err_t mpu9250_get_gyroscope(rt_int16_t *gx, rt_int16_t *gy, rt_int16_t *gz)
{rt_uint8_t buf[6], ret;ret = mpu9250_read_regs(MPU_GYRO_XOUTH_REG, 6, buf);if (ret == 0){*gx = ((rt_uint16_t)buf[0] << 8) | buf[1];*gy = ((rt_uint16_t)buf[2] << 8) | buf[3];*gz = ((rt_uint16_t)buf[4] << 8) | buf[5];return RT_EOK;}else{return -RT_ERROR;}
}
rt_err_t mpu9250_get_accelerometer(rt_int16_t *ax, rt_int16_t *ay, rt_int16_t *az)
{rt_uint8_t buf[6], ret;ret = mpu9250_read_regs(MPU_ACCEL_XOUTH_REG, 6, buf);if (ret == 0){*ax = ((rt_uint16_t)buf[0] << 8) | buf[1];*ay = ((rt_uint16_t)buf[2] << 8) | buf[3];*az = ((rt_uint16_t)buf[4] << 8) | buf[5];return RT_EOK;}else{return -RT_ERROR;}
}
rt_err_t mpu9250_get_magnetometer(rt_int16_t *mx, rt_int16_t *my, rt_int16_t *mz)
{rt_uint8_t buf[6], ret;ret = mpu9250_read_magnetometer_regs(MAG_XOUT_L, 6, buf);if (ret == 0){*mx = ((rt_uint16_t)buf[0] << 8) | buf[1];*my = ((rt_uint16_t)buf[2] << 8) | buf[3];*mz = ((rt_uint16_t)buf[4] << 8) | buf[5];return RT_EOK;}else{return -RT_ERROR;}
}//传送数据给匿名四轴上位机软件(V2.6版本)
//fun:功能字. 0X01~0X1C
//data:数据缓存区,最多28字节!!
//len:data区有效数据个数
void usart1_niming_report(rt_uint8_t fun, rt_uint8_t *data, rt_uint8_t len)
{rt_uint8_t send_buf[32];rt_uint8_t i;if (len > 28)return; //最多28字节数据send_buf[len + 3] = 0; //校验数置零send_buf[0] = 0XAA; //帧头send_buf[1] = 0XAA; //帧头send_buf[2] = fun; //功能字send_buf[3] = len; //数据长度for (i = 0; i < len; i++)send_buf[4 + i] = data[i]; //复制数据for (i = 0; i < len + 4; i++)send_buf[len + 4] += send_buf[i]; //计算校验和for (i = 0; i < len + 5; i++)wireless_putchar(send_buf[i]); //发送数据到串口1
}
//发送加速度传感器数据+陀螺仪数据(传感器帧)
//aacx,aacy,aacz:x,y,z三个方向上面的加速度值
//gyrox,gyroy,gyroz:x,y,z三个方向上面的陀螺仪值
void mpu6050_send_data(short aacx, short aacy, short aacz, short gyrox, short gyroy, short gyroz)
{rt_uint8_t tbuf[18];tbuf[0] = (aacx >> 8) & 0XFF;tbuf[1] = aacx & 0XFF;tbuf[2] = (aacy >> 8) & 0XFF;tbuf[3] = aacy & 0XFF;tbuf[4] = (aacz >> 8) & 0XFF;tbuf[5] = aacz & 0XFF;tbuf[6] = (gyrox >> 8) & 0XFF;tbuf[7] = gyrox & 0XFF;tbuf[8] = (gyroy >> 8) & 0XFF;tbuf[9] = gyroy & 0XFF;tbuf[10] = (gyroz >> 8) & 0XFF;tbuf[11] = gyroz & 0XFF;tbuf[12] = 0; //因为开启MPL后,无法直接读取磁力计数据,所以这里直接屏蔽掉.用0替代.tbuf[13] = 0;tbuf[14] = 0;tbuf[15] = 0;tbuf[16] = 0;tbuf[17] = 0;usart1_niming_report(0X02, tbuf, 18); //传感器帧,0X02
}
//通过串口1上报结算后的姿态数据给电脑(状态帧)
//roll:横滚角.单位0.01度。 -18000 -> 18000 对应 -180.00 -> 180.00度
//pitch:俯仰角.单位 0.01度。-9000 - 9000 对应 -90.00 -> 90.00 度
//yaw:航向角.单位为0.1度 0 -> 3600 对应 0 -> 360.0度
//csb:超声波高度,单位:cm
//prs:气压计高度,单位:mm
void usart1_report_imu(short roll, short pitch, short yaw, short csb, int prs)
{rt_uint8_t tbuf[12];tbuf[0] = (roll >> 8) & 0XFF;tbuf[1] = roll & 0XFF;tbuf[2] = (pitch >> 8) & 0XFF;tbuf[3] = pitch & 0XFF;tbuf[4] = (yaw >> 8) & 0XFF;tbuf[5] = yaw & 0XFF;tbuf[6] = (csb >> 8) & 0XFF;tbuf[7] = csb & 0XFF;tbuf[8] = (prs >> 24) & 0XFF;tbuf[9] = (prs >> 16) & 0XFF;tbuf[10] = (prs >> 8) & 0XFF;tbuf[11] = prs & 0XFF;usart1_niming_report(0X01, tbuf, 12); //状态帧,0X01
}void mpu9250_thread_entry(void *parameter)
{float pitch, roll, yaw; //欧拉角short *temp; //温度while (1){
// if (mpu_mpl_get_data(&pitch, &roll, &yaw) == 0)
// {
// rt_mutex_take(&Mpu9250Mutex, RT_WAITING_FOREVER);
// mypitch=pitch;
// myroll=roll;
// myyaw=yaw;
// printf("myyaw: %f | myroll: %f |mypitch: %f \r\n",myyaw,myroll,mypitch);
// rt_mutex_release(&Mpu9250Mutex);
// }mpu9250_get_temperature(*temp); //得到温度值
// rt_kprintf("%f", temp);rt_thread_delay(rt_tick_from_millisecond(200));}
}//#include "inv_mpu.h"
int mpu9250_init(void)
{rt_uint8_t res;rt_device_t dev;rt_thread_delay(rt_tick_from_millisecond(100));dev = rt_device_find(MPU9250_I2CBUS_NAME);if (dev == RT_NULL){MPUDEBUG("can't find mpu9250 %s device\r\n", MPU9250_I2CBUS_NAME);return -RT_ERROR;}if (rt_device_open(dev, RT_DEVICE_OFLAG_RDWR) != RT_EOK){MPUDEBUG("can't opend mpu9250 %s device\r\n", MPU9250_I2CBUS_NAME);return -RT_ERROR;}//获取i2c设备句柄mpu9250_i2c_bus = (struct rt_i2c_bus_device *)dev;mpu9250_write_reg(MPU_PWR_MGMT1_REG,0X80);//复位MPU9250rt_thread_delay(100); //延时100msmpu9250_write_reg(MPU_PWR_MGMT1_REG,0X00);//唤醒MPU9250mpu9250_set_gyro_fsr(3); //陀螺仪传感器,±2000dpsmpu9250_set_accel_fsr(0); //加速度传感器,±2gmpu9250_set_sample_rate(50); //设置采样率50Hzmpu9250_write_reg(MPU_INT_EN_REG,0X00); //关闭所有中断mpu9250_write_reg(MPU_USER_CTRL_REG,0X00);//I2C主模式关闭mpu9250_write_reg(MPU_FIFO_EN_REG,0X00); //关闭FIFOmpu9250_write_reg(MPU_INTBP_CFG_REG,0X82);//INT引脚低电平有效,开启bypass模式,可以直接读取磁力计mpu9250_read_reg(MPU_DEVICE_ID_REG,res); //读取MPU6500的IDif(res==MPU6500_ID) //器件ID正确{mpu9250_write_reg(MPU_PWR_MGMT1_REG,0X01); //设置CLKSEL,PLL X轴为参考mpu9250_write_reg(MPU_PWR_MGMT2_REG,0X00); //加速度与陀螺仪都工作mpu9250_set_sample_rate(50); //设置采样率为50Hz}else return -RT_ERROR;
//
// res=mpu9250_read_reg(AK8963_ADDR,MAG_WIA); //读取AK8963 ID
// if(res==AK8963_ID)
// {
// mpu9250_write_reg(AK8963_ADDR,MAG_CNTL2,0X01); //复位AK8963
// rt_thread_delay(50);
// mpu9250_write_reg(AK8963_ADDR,MAG_CNTL1,0X11); //设置AK8963为单次测量
// }else return -RT_ERROR;// MPUDEBUG("mpu_dmp_init is runing !\r\n");
//
// while (mpu_dmp_init())
// {
// MPUDEBUG("mpu_dmp_init waiting ! 0x%02x\r\n", res);
// rt_thread_delay(rt_tick_from_millisecond(100));
// }
// MPUDEBUG("mpu_dmp_init is ok !\r\n");// rt_thread_t tid;
// /* 创建 MPU9250 线程 *//
// tid = rt_thread_create("mpu9250",
// mpu9250_thread_entry,
// RT_NULL,
// 2048,
// 3,
// 20);
// /* 创建成功则启动线程 */
// if (tid != RT_NULL)
// rt_thread_startup(tid);return RT_EOK;}static void mpu9250_sample()
{float pitch,roll,yaw; //欧拉角rt_int16_t aacx,aacy,aacz; //加速度传感器原始数据rt_int16_t gyrox,gyroy,gyroz; //陀螺仪原始数据rt_int16_t mx,my,mz; //磁力计原始数据short temp; //温度mpu9250_get_temperature(temp); //得到温度值mpu9250_get_accelerometer(&aacx,&aacy,&aacz); //得到加速度传感器数据mpu9250_get_gyroscope(&gyrox,&gyroy,&gyroz); //得到陀螺仪数据mpu9250_get_magnetometer(mx, my, mz);rt_kprintf("%d, %d %d %d, %d %d %d, %d %d %d\r\n", temp, aacx, aacy, aacz,gyrox, gyroy, gyroz, mx, my, mz);}//reg:寄存器地址
//data:数据指针
//返回值:0,正常
// -1,错误代码
rt_err_t mpu9250_read_reg_sample(int argc, char *argv[])
{rt_uint8_t reg=0;rt_uint8_t data=0;if (argc == 2){reg=argv[1];}struct rt_i2c_msg msgs[2];msgs[0].addr = MPU9250_ADDR;msgs[0].flags = RT_I2C_WR;msgs[0].buf = ®msgs[0].len = 1;msgs[1].addr = MPU9250_ADDR;msgs[1].flags = RT_I2C_RD;msgs[1].buf = data;msgs[1].len = 1;if (rt_i2c_transfer(mpu9250_i2c_bus, msgs, 2) == 2){rt_kprintf("addr=0x%2x, data=0x%x \r\n", reg, data);return RT_EOK;}elsereturn -RT_ERROR;
}
MSH_CMD_EXPORT(mpu9250_sample, mpu9250 sample);
MSH_CMD_EXPORT(mpu9250_read_reg_sample, mpu9250 read reg sample);
在main.c的main函数主循环中添加测试代码:
mpu9250_get_temperature(temp); //得到温度值mpu9250_get_accelerometer(&aacx,&aacy,&aacz); //得到加速度传感器数据mpu9250_get_gyroscope(&gyrox,&gyroy,&gyroz); //得到陀螺仪数据mpu9250_get_magnetometer(&mx, &my, &mz);rt_kprintf("%d, %d %d %d, %d %d %d, %d %d %d -- c\r\n", temp, aacx, aacy, aacz,gyrox, gyroy, gyroz, mx, my, mz);
发现能输出原始数据,但这些原始数据不解算的话没有意义,在调用mpu_dmp_init()函数时发现了很多问题。
经过反复地仔细地阅读正点原子的代码,发现仅仅将其工程下文件夹DMP复制过来是不行的,需要跟多的修改。首先是将其源代码文件复制过来,包括sys.h、sys.c、delay.h、delay.c、myiic.h、myiic.c、mpu9250.h和mpu9250.c文件。其次是studio项目属性中的设置,
添加宏定义如下:

添加include路径:

添加库文件:

上面第三个图是添加库文件,要选择motion_driver_6.12官方原包里下的gcc编译环境对应的库文件(studio是gcc编译,正点原子是keil编译,方式不同),具体路径是“motion_driver_6.12\mpl libraries\arm\gcc4.9.3\liblibmplmpu_m4_hardfp.zip”,解压出来添加到studio项目。特别要注意的是,在添加库的时候,库文件名的前三个字母“lib”需要去掉。
测试
为了在匿名科创地面站V4显示数据波形和飞控状态,串口波特率设置为500000.
修改main函数,部分代码如下:
int main(void)
{int count = 1;u8 t=0,report=1; //默认开启上报u8 key;float pitch,roll,yaw; //欧拉角short aacx,aacy,aacz; //加速度传感器原始数据short gyrox,gyroy,gyroz; //陀螺仪原始数据short mx,my,mz; //磁力计原始数据short temp; //温度sd_rw();/* 传感器初始化 */mpu9250_init();if(MPU9250_Init()){rt_kprintf("MPU9250_Init failed! \r\n");}while(0) {temp=MPU_Get_Temperature(); //得到温度值MPU_Get_Accelerometer(&aacx,&aacy,&aacz); //得到加速度传感器数据MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz); //得到陀螺仪数据MPU_Get_Magnetometer(&mx, &my, &mz);rt_kprintf("%d, %d %d %d, %d %d %d, %d %d %d\r\n", temp, aacx, aacy, aacz,gyrox, gyroy, gyroz, mx, my, mz);rt_thread_mdelay(200);mpu9250_get_temperature(temp); //得到温度值mpu9250_get_accelerometer(&aacx,&aacy,&aacz); //得到加速度传感器数据mpu9250_get_gyroscope(&gyrox,&gyroy,&gyroz); //得到陀螺仪数据mpu9250_get_magnetometer(&mx, &my, &mz);rt_kprintf("%d, %d %d %d, %d %d %d, %d %d %d -- c\r\n", temp, aacx, aacy, aacz,gyrox, gyroy, gyroz, mx, my, mz);rt_thread_mdelay(200);}rt_kprintf("mpu_dmp_init=%d\r\n",mpu_dmp_init());while(mpu_dmp_init()){rt_kprintf("MPU9250 Error\r\n");//mpu9250_sample();rt_thread_mdelay(500);}// aht10_init(AHT10_I2C_BUS_NAME);LOG_D("Enter main!\r\n");while(1){if(mpu_mpl_get_data(&pitch,&roll,&yaw)==0){temp=MPU_Get_Temperature(); //得到温度值MPU_Get_Accelerometer(&aacx,&aacy,&aacz); //得到加速度传感器数据MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz); //得到陀螺仪数据rt_thread_mdelay(10);if((t%20)==0){rt_kprintf("%d, %d %d %d, %d %d %d\r\n", temp, aacx, aacy, aacz,gyrox, gyroy, gyroz);rt_kprintf("%d, %d, %d \r\n", (int)(roll*100),(int)(pitch*100),(int)(yaw*100),0,0);}}t++;}while (count++){rt_thread_mdelay(1000);}return RT_EOK;
}
系统启动前,需要将MPU9250模块放平。两种IIC方式对比了下,都没有问题。
最后接入匿名科创地面站V4,

这样就可以在数据波形和飞控状态中看到东西了。
总结
本以为移植mpu9250的驱动是最难的,结果发现启用dmp才是最难的。最后为了省事,直接将正点原子的代码文件小改后复制进项目,搞得有点儿不伦不类。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
