IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> RT-Thread Studio学习(十)MPU9250 -> 正文阅读

[嵌入式]RT-Thread Studio学习(十)MPU9250

简介

本文将基于STM32F407VET芯片介绍如何在RT-Thread Studio开发环境下运用9轴传感器MPU9250。

新建RT-Thread项目并使用外部时钟

详细步骤参考文档《RT-Thread Studio学习(一)使用外部时钟系统》。

设置MPU9250的驱动框架

RT-Thread Studio设置
使能如下组件并进行配置:
在这里插入图片描述
board.h文件中使能I2C1:
在这里插入图片描述

驱动代码的移植

参考正点原子阿波罗F429的MPU9250实验,进行了相应的移植。
首先是直接移植mpu9250.hmpu9250.c文件,修改为app_mpu9250.happ_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 <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>

#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 <rthw.h>
#include <rtdevice.h>

#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(...)
#endif

static 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;
    else
        return -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   = &reg;
    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;
    else
        return -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;
    else
        return -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;
    else
        return -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   = &reg;
    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;
    else
        return -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   = &reg;
    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   = &reg;
    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   = &reg;
    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;
    else
        return -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);//复位MPU9250
    rt_thread_delay(100);  //延时100ms
    mpu9250_write_reg(MPU_PWR_MGMT1_REG,0X00);//唤醒MPU9250
    mpu9250_set_gyro_fsr(3);                                //陀螺仪传感器,±2000dps
    mpu9250_set_accel_fsr(0);                               //加速度传感器,±2g
    mpu9250_set_sample_rate(50);                        //设置采样率50Hz
    mpu9250_write_reg(MPU_INT_EN_REG,0X00);   //关闭所有中断
    mpu9250_write_reg(MPU_USER_CTRL_REG,0X00);//I2C主模式关闭
    mpu9250_write_reg(MPU_FIFO_EN_REG,0X00);  //关闭FIFO
    mpu9250_write_reg(MPU_INTBP_CFG_REG,0X82);//INT引脚低电平有效,开启bypass模式,可以直接读取磁力计
    mpu9250_read_reg(MPU_DEVICE_ID_REG,res);  //读取MPU6500的ID
    if(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   = &reg;
    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;
    }
    else
        return -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才是最难的。最后为了省事,直接将正点原子的代码文件小改后复制进项目,搞得有点儿不伦不类。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-07-05 20:25:18  更:2021-07-05 20:25:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 9:38:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计