目录

1. 初始化I2C
2. 读取who_an_I,验证I2C设置和芯片函数正确性
3. 读取ACC,GYR数据,验证芯片正常工作
4. 用DMP算法,计算芯片欧拉角


1.初始化I2C
I2C可以分为软件形式和硬件形式,这边使用的是硬件形式。


这里介绍一下I2C的读写顺序,了解的可以跳过


硬件:使用的主芯片是ESP32S3MPU6500

注意点一:mpu6500共有两种通信方式SPI和I2C。默认是SPI,当CS高电平,SPI有效,当CS低电平,SPI是无效的,此时可以用I2C通信。可以变相理解CS就是区分SPI和I2C的开关。如上图,CS接地,使用的是SPI通信。(为了搞清楚这个花了一天)。
注意点二:esp32有两个I2C,依据在stm32的经验,自然的认为这两个I2C是对应特定的引脚(找了好多资料也没有找到)。其实不然,其可以映射到任意的两个GPIO口
硬件初始化

#define I2C_MASTER_NUM   0//esp32有2个I2C,0和1,这里选择0
#define SDI              2
#define SCLK             1
#define I2C_MASTER_FREQ_HZ          100000int i2c_master_port = I2C_MASTER_NUM;i2c_config_t conf = {.mode = I2C_MODE_MASTER,   //设置通信模式,这里设置为主机.sda_io_num = SDI,         //设置I2C的SDA脚对应的I0引脚.scl_io_num = SCLK,        //设置I2C的SCL脚对应的I0引脚.sda_pullup_en = GPIO_PULLUP_ENABLE, //SDA脚上拉.scl_pullup_en = GPIO_PULLUP_ENABLE, //SCL脚上拉.master.clk_speed = I2C_MASTER_FREQ_HZ,   //设置通信速度};i2c_param_config(i2c_master_port, &conf);  //设置I2C参数i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);//注册I2C

2. 读取who_an_I,验证I2C设置和芯片函数正确性

/***********************************************************************************************************函 数 名: MPU6500_who_am_I*功能说明: 读取芯片ID*形    参: 无*返 回 值: 无**********************************************************************************************************/#define who_am_I                    0x70//MPU6500的ID号应该是0x70#define MPU6500_WHO_AM_I_REG_ADDR   (0x75) // mpu6500 id = 0x70
uint8_t MPU6500_who_am_I (void)
{uint8_t data=0x30;MPU6500_register_read(MPU6500_WHO_AM_I_REG_ADDR, &data, 1);if (data==who_am_I){printf("MPU6500_is_OK");           }else{printf("MPU6500_is_Wrong");}    return data;
}

一个读取函数,一个写入函数

/***********************************************************************************************************函 数 名: MPU6500_register_read*功能说明: IIC连续读*形    参: reg_addr:要读取的寄存器地址、data:读取到的数据存储区、len:要读取的长度*返 回 值: 0,成功、其他,错误代码**********************************************************************************************************/#define MPU6500_SENSOR_ADDR         0x68    //SD0脚接地地址是0x68,SD0脚接VCC地址是0x69esp_err_t MPU6500_register_read(uint8_t reg_addr, uint8_t *data, size_t len)
{int ret;ret=i2c_master_write_read_device(I2C_MASTER_NUM, MPU6500_SENSOR_ADDR, &reg_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);   return ret;
}
/***********************************************************************************************************函 数 名: MPU6500_register_write_byte*功能说明: IIC写单个*形    参: reg_addr:要读取的寄存器地址、data:读取到的数据存储区*返 回 值: 0,成功、其他,错误代码**********************************************************************************************************/esp_err_t MPU6500_register_write_byte(uint8_t reg_addr, uint8_t data)
{int ret;uint8_t write_buf[2] = {reg_addr, data};ret = i2c_master_write_to_device(I2C_MASTER_NUM, MPU6500_SENSOR_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);  return ret;
}

这里曾经为MPU6500_SENSOR_ADDR,也就是设备地址迷惑过一段时间,这个数值是7位还是8位,后来看了官方提供的读写函数确定才是7位的。


3. 读取ACC,GYR数据,验证芯片正常工作
验证好连接正常后,就要读取数据看看芯片工作是否正常

/*这14个寄存器存储加速度、陀螺仪、温度的原始数据*/
#define MPU6500_ACCEL_XOUT_H        (0x3B)
#define MPU6500_ACCEL_XOUT_L        (0x3C)
#define MPU6500_ACCEL_YOUT_H        (0x3D)
#define MPU6500_ACCEL_YOUT_L        (0x3E)
#define MPU6500_ACCEL_ZOUT_H        (0x3F)
#define MPU6500_ACCEL_ZOUT_L        (0x40)
#define MPU6500_TEMP_OUT_H          (0x41)
#define MPU6500_TEMP_OUT_L          (0x42)
#define MPU6500_GYRO_XOUT_H         (0x43)
#define MPU6500_GYRO_XOUT_L         (0x44)
#define MPU6500_GYRO_YOUT_H         (0x45)
#define MPU6500_GYRO_YOUT_L         (0x46)
#define MPU6500_GYRO_ZOUT_H         (0x47)
#define MPU6500_GYRO_ZOUT_L         (0x48)esp_err_t mpu6500_GYR_read(uint8_t GYR_DATA[])
{ESP_ERROR_CHECK(mpu9250_register_read(MPU6500_GYRO_XOUT_H, &GYR_DATA[0], 1));ESP_ERROR_CHECK(mpu9250_register_read(MPU6500_GYRO_XOUT_L, &GYR_DATA[1], 1));ESP_ERROR_CHECK(mpu9250_register_read(MPU6500_GYRO_YOUT_H, &GYR_DATA[2], 1));ESP_ERROR_CHECK(mpu9250_register_read(MPU6500_GYRO_YOUT_L, &GYR_DATA[3], 1));ESP_ERROR_CHECK(mpu9250_register_read(MPU6500_GYRO_ZOUT_H, &GYR_DATA[4], 1));ESP_ERROR_CHECK(mpu9250_register_read(MPU6500_GYRO_ZOUT_L, &GYR_DATA[5], 1));return ESP_OK;
}
/**********/
esp_err_t mpu6500_ACC_cal(double ACC_DATA_CAL[])
{uint8_t data_config=0;uint8_t val_config=0;uint16_t val[3]={};double val_true[3]={};mpu6500_ACC_read(ACC_DATA);val[0]=ACC_DATA[0]*256+ACC_DATA[1];val[1]=ACC_DATA[2]*256+ACC_DATA[3];val[2]=ACC_DATA[4]*256+ACC_DATA[5];ESP_LOGI(TAG_mpu6500, "val[0] = %d", val[0]);ESP_LOGI(TAG_mpu6500, "val[1] = %d", val[1]);ESP_LOGI(TAG_mpu6500, "val[2] = %d", val[2]);//读取加速度计配置ESP_ERROR_CHECK(mpu9250_register_read(MPU6500_GYRO_CONFIG, &data_config, 1));val_config=(data_config&0x18)>>3;ESP_LOGI(TAG_mpu6500, "val_config = %d", val_config);if (val_config==0){/* code */val_true[0]=val[0];val_true[1]=val[1];val_true[2]=val[2];val_true[0]=val_true[0]/32768;val_true[1]=val_true[1]/32768;val_true[2]=val_true[2]/32768;ESP_LOGI(TAG_mpu6500, "x_true = %f", val_true[0]);ESP_LOGI(TAG_mpu6500, "y_true = %f", val_true[1]);ESP_LOGI(TAG_mpu6500, "z_true = %f", val_true[2]);}double R=sqrt(powl(val_true[0],2)+powl(val_true[1],2)+powl(val_true[2],2));ESP_LOGI(TAG_mpu6500, "R = %f", R);double x_cos,y_cos,z_cos;x_cos=sqrt(powl(val_true[0],2)+powl(val_true[1],2))/R;y_cos=sqrt(powl(val_true[0],2)+powl(val_true[2],2))/R;z_cos=sqrt(powl(val_true[1],2)+powl(val_true[2],2))/R;ESP_LOGI(TAG_mpu6500, "x_cos = %f", x_cos);ESP_LOGI(TAG_mpu6500, "y_cos = %f", y_cos);ESP_LOGI(TAG_mpu6500, "z_cos = %f", z_cos);double xy=acos(x_cos);double xz=acos(y_cos);double yz=acos(z_cos);ACC_DATA_CAL[0]=xy;ACC_DATA_CAL[1]=xz;ACC_DATA_CAL[2]=yz;return ESP_OK;}


这中间其实有一段迷茫时候,有数据而不知道怎么用,就像下面的这段话,觉得挺有意思
然后不知道干什么了。不太能想想空间中的运动状态,可以想飞机的飞行姿态。由于时间关系这个探讨展示就到这里,后续有个思考是,做一个飞行器的上位机,把获取到数据转化成飞行姿态,这个时候可能就知道用处了。希望这一个月内,还有机会做这个事情。
进行数据处理带来的思考。玩了两天,还是没有明白得到的数据该怎么进行处理得到一个有作用的东西。
有篇文章说的是数据该怎么算,看了后,我还是没有明白,这些数据得到后有什么用。关于角度的解释,在这里我其实是认为,完全可以计算出重量相对于三个的面的夹角的,其实应该是6个夹角,每个面有两个,任意一个面都是有两个面跟它垂直。计算飞行姿态?


4. 用DMP算法,计算芯片欧拉角
这是官方推荐的算法,有一个算法库(0积分下载,如果有积分请联系QQ:3410968441),可以融合加速度和陀螺仪算欧拉角。

在inv_mpu.h文件中有

typedef uint8_t  u8;
int mpu_init(void);//初始化MPu6500
u8 mpu_dmp_init(void);//初始化dmp
u8 mpu_dmp_get_data(float *pitch,float *roll,float *yaw);//获取欧拉角

使用时候调用这三个方法就可以(如果使用官方的库,就不用自己写初始化函数,只要改改读写和延时函数就可以了)
值得注意的一点是,在使用之前要设置一下,写,读和延时函数

#define i2c_write   MPU_Write_Len
#define i2c_read    MPU_Read_Len
#define delay_ms    MPU_Delayms
#define get_ms      mget_ms

前面的i2c_write,i2c_read,delay_ms都是官方固件读写用的函数,但是没有写具体的方法,这个对应不同的芯片,需要用户自己写后面的MPU_Write_Len,MPU_Read_Len,MPU_Delayms三个函数。

/***********************************************************************************************************函 数 名: MPU_Write_Len*功能说明: IIC连续写*形    参: addr:器件地址、reg:寄存器地址、len:写入长度、buf:数据区*返 回 值: 0,成功、其他,错误代码**********************************************************************************************************/
esp_err_t MPU_Write_Len(uint8_t addr, uint8_t reg, uint8_t len, uint8_t *buf)
{int ret;uint8_t write_buf[1 + len];write_buf[0] = reg;memcpy(&write_buf[1], buf, len);ret = i2c_master_write_to_device(0, addr, write_buf, 1 + len, 100 / portTICK_RATE_MS);return ret;
}
/***********************************************************************************************************函 数 名: MPU_Read_Len*功能说明: IIC连续读*形    参: addr:器件地址、reg:要读取的寄存器地址、len:要读取的长度、buf:读取到的数据存储区*返 回 值: 0,成功、其他,错误代码**********************************************************************************************************/
esp_err_t MPU_Read_Len(uint8_t addr, uint8_t reg, uint8_t len, uint8_t *buf)
{return i2c_master_write_read_device(0, addr, &reg, 1, buf, len, 100 / portTICK_RATE_MS);
}
/***********************************************************************************************************函 数 名: MPU_Delayms*功能说明: 毫秒延时*形    参: time:延时时间*返 回 值: **********************************************************************************************************/
void MPU_Delayms(int time)
{vTaskDelay(time/portTICK_RATE_MS);
}

这边轮询调用mpu_dmp_get_data函数速度不能太慢,不然有机会卡死,输出数据不变,我用的是1kHZ,还可以使用中断方式读取。

esp32和MPU6500 I2C通信相关推荐

  1. linux stm32 主从,STM32F407和STM32F051主从I2C通信方法

    STM32F407和STM32F051主从I2C通信方法 作者:华清远见讲师 M4作为主机: int main(void) { HAL_Init(); SystemClock_Config(); MX ...

  2. AT24C0X I2C通信原理

    /*********************************************************************** AT24C0X I2C通信原理* 说明:* 之前接触A ...

  3. 快速对比UART、SPI、I2C通信的区别与应用

    参考:带你快速对比SPI.UART.I2C通信的区别与应用! 作者:一口Linux 网址:https://mp.weixin.qq.com/s/4_RSM2jk2W6nTboO1W8HCw 电子设备之 ...

  4. i2c通信的详细讲解_【博文连载】SCCB(I2C)初始化时序介绍

    在正式开始OV7725视频采集实现之前,Bingo不得不先讲解一下OV7725的寄存器配置接口.OV7725上电会默认输出YUV422格式的视频流,但我们希望传感器能够按照我们预期的模式工作,我们需要 ...

  5. STM32 I2C通信(读写eeprom)

    I2C通信 双线制:串行时钟线SCL,串行数据线SDA. 通常采用软件模拟i2c通信.

  6. I2C通信读写数据过程

    1.先来看读数据的操作流程 这里面需要注意的有: I2C通信启动后面不需要等待应答信号 写入数据地址之后,下一步不能直接进行读取数据,需要先再一次地开启动I2C通信才可以 程序如下: u8 x24c0 ...

  7. STM32应用(七)JY901九轴姿态模块(串口DMA空闲中断和I2C通信)

    文章目录 0.相关基础知识介绍 0.1六轴.九轴传感器有什么区别? 1.JY901模块简介 1.1 产品概述 1.2 性能参数 1.3 实物图和接线 2.软件和使用说明书 3.串口通信JY901 3. ...

  8. 基于距离传感器的I2C通信(一)

    基于距离传感器的I2C通信(一) 一.软硬件准备 (一)硬件 (二)软件 ST-Link驱动的下载安装 二.keil软件的配置 (一)初始配置 (二)程序下载及调试 三.器件的初步了解 四.接线方法 ...

  9. 【FPGA】十一、I2C通信回环

    文章目录 前言 一.I2C简介 二.I2C原理 2.1.I2C物理层 2.2.I2C协议层 2.2.1.I2C协议 2.2.2.I2C数据传输格式 2.2.3.I2C写操作 2.2.4.I2C读操作 ...

最新文章

  1. 由粗到精学习LVI-SAM基础:多传感器内外参标定原理
  2. 在这个问题上,能看出 Java 工程师的真实水平
  3. android wm 改变大小,Android 屏幕适配经验总结
  4. Activity-数据状态的保存
  5. pandas Dataframe表格转Markdown格式
  6. python语言在命名上是什么敏感的_一文轻松掌握python语言命名规范规则
  7. Solidity-让合约地址 接受ETH的转账充值的 三种方式
  8. PHP模板引擎Smarty概述
  9. Java基础笔记(2) 程序入口 关键字 标识符 常量 变量
  10. couchdb 安装_如何在Ubuntu上安装CouchDB –分步指南
  11. zabbix配置飞信报警
  12. Android 开发中常见的Eclipse排版设置
  13. Linux常用命令——cd
  14. sql top加不加括号的区别_SQL易错点大作战
  15. ubuntu pip安装xgboost
  16. WebX框架解析及使用教程
  17. 我的世界服务器修改世界难度,我的世界服务器空岛生存调难度指令 | 手游网游页游攻略大全...
  18. 国际云安全证书CCSK让他们在职场中脱颖而出
  19. socks5协议详细说明
  20. 使用javascript实现对于chineseocr的API调用

热门文章

  1. j计算机职称考试题库,2017职称计算机考试题库「附答案」
  2. DDCTF2020 Writeup
  3. 个人信息保护建设面临的问题和困境及解决方案
  4. Android 如何判断分屏模式是否开启或者多窗口显示
  5. AIX系统更换本地硬盘
  6. 计算机网络安规模分类,1计算机网络按规模分类
  7. 道德经·太上,不知有之
  8. 基于SSM开发校园外卖零食购物商城系统
  9. hdu 1850 Being a Good Boy in Spring Festival (尼姆博弈)
  10. 从《羊了个羊》看随机数的生成原理