文章目录

  • 实验目的
  • 实验步骤
  • 实验分析
  • 源码分析
    • 主函数
    • I2C初始化
    • I2C_Write_Byte
    • IIC_Start
    • IIC_SendByte
    • GetMPU6050Offset
    • GetMPU6050Data
    • MPU6050Manager_t结构体

实验目的

  • 基于MSP430处理器的 I2C总线读取MPU6050传感器数据
  • 将读取到的数据通过串口显示在上位机控制终端上

实验步骤

  • 硬件连接
  • 下载程序

实验分析

  • 硬件I2C功能(直接使用,X不用在意)
  • 普通I/O口模拟I2C时序(本实验采用)

源码分析

主函数

#include "include.h"
void main()
{WDT_A_hold(WDT_A_BASE);_DINT();  //禁止所有中断Hardware_Init();//硬件初始化  _EINT();//使能中断while (1){PollingKernel();  }
}
  • 使用定时器中断定时读取数据
  • 使用串口中断传输数据(显示在控制终端上)
void Hardware_Init(void)
{System_Clock_Init();I2C_Init();            //IO口模拟IIC时序Motor_Init();LEDInit();         //LED灯闪初始化MPU6050Init();        //g_MPUManager初始化SPL06_Init();      //SPL06初始化NRF_Radio_Init(); if(HARDWARE_CHECK)  //硬件检测{g_LedManager.emLEDPower = PowerOn;}gcs_init();          //地面站通信初始化PID_Init();           //PID参数初始化   USART_Init(USCI_A_UART_CLOCKSOURCE_ACLK,115200);Timer_Init();}

I2C初始化

/**************************************************************************************函数名称:I2C_Init*函数描述:初始化I2C总线*输   入:void*输   出:void*返   回:void*备   注:null**
*************************************************************************************/void I2C_Init()
{//P3.1是SCL时钟P3DIR |= (1 << SCL); //方向寄存器,P3.1置1,设为输出,看上图
}
//宏定义
#define     SCL     1#define    IIC_SDA_Out     P3DIR |= BIT0
#define     IIC_SDA_In      P3DIR &= ~BIT0
#define     IIC_SCL_Out     P3DIR |= BIT1

##MPU6050的寄存器初始化

/**************************************************************************************函数名称:MPU6050Init*函数描述:g_MPUManager的初始化*输   入:void*输   出:g_MPUManager初始化结果*           0:初始化成功*         1:初始化失败*返   回:void*备   注:null**
*************************************************************************************/
//就是初始化寄存器
bool MPU6050Init(void)
{uint8_t check =0;//从机地址B11010000(最后一位是写位),寄存器地址I2C_Write_Byte(MPU6050_ADDRESS, PWR_MGMT_1,       0x80);  //复位delay_ms(30);//陀螺仪采样率,0x00(333Hz) //经验总结的333Hz=1000/(1+2)I2C_Write_Byte(MPU6050_ADDRESS, SMPLRT_DIV,     0x02);//设置设备时钟源,陀螺仪Z轴I2C_Write_Byte(MPU6050_ADDRESS, PWR_MGMT_1,     0x03); //低通滤波频率,0x03(42Hz)I2C_Write_Byte(MPU6050_ADDRESS, CONFIGL,       0x03); // +-2000deg/s  //陀螺仪量程I2C_Write_Byte(MPU6050_ADDRESS, GYRO_CONFIG, 0x18); // +-4g  //加速度量程I2C_Write_Byte(MPU6050_ADDRESS, ACCEL_CONFIG,   0x09); //0x75寄存器中保存了从机地址check = I2C_Read_Byte(MPU6050_ADDRESS, 0x75);   //判断g_MPUManager地址if(check != MPU6050_PRODUCT_ID)//如果地址不正确{g_MPUManager.Check = false;return false;}else{//静止状态下,除了Z轴的加速度g外全都为零GetMPU6050Offset(); //调用校准数据g_MPUManager.Check = true;return true;}
}

I2C_Write_Byte

//遵循I2C协议的时序图
void I2C_Write_Byte(uint8_t Slaveaddr, uint8_t REG_Address, uint8_t REG_data)
{IIC_Start();  //发送起始信号IIC_SendByte(Slaveaddr);   //从机地址B11010000(最后一位是写位)IIC_SendByte(REG_Address);IIC_SendByte(REG_data);IIC_Stop();
}

//宏定义
#define     SDA     0
//P3OUT是P3口寄存器
#define     IIC     P3OUT

IIC_Start


void IIC_Start()
{//P3.0是SDA线P3DIR |= (1 << SDA);  //P3.0置1,设为输出IIC |= (1 << SDA);    //P3.0输出1,SDA高电平delay(1);   //让数据保持一段时间(电平嘛)IIC |= (1 << SCL);    //P3.1输出1,SCL高电平delay(1);  //延时1msIIC &= ~(1 << SDA);  //P3.0输出0,SDA低电平delay(1);IIC &= ~(1 << SCL);  //P3.1输出0,SCL低电平 为后面发送地址做准备//所以将SCL拉低delay(1);
}

IIC_SendByte

  • 延时的作用当然是让数据保持一段时间(电平嘛),因为传输信号是 TTL 电平信号。 确保数据已经写入,从主机写入外设需要时间的
void IIC_SendByte(uint32_t dat)
{uint32_t i;P3DIR |= (1 << SDA);   //P3.0置1,设为输出i = 8; //八位数据需要发送IIC &= ~(1 << SCL);  //P3.1输出0,SCL低电平delay(1);  //延时1mswhile(i--){//为啥要从最高位发送呢?规定if((dat & 0x80) >> 7)  //判断最高位是0还是1,然后写入P3.0,写入总线{IIC |=  (1 << SDA); //P3.0输出1}else{IIC &= ~(1 << SDA); //P3.0输出0}dat  <<= 1;   //将数据(地址)左移一位delay(1);  IIC |= (1 << SCL);  //P3.1高电平,SCL高电平delay(1);IIC &= ~(1 << SCL); //P3.1低电平,SCL低电平,为写下一位数据做准备delay(1);}IIC |= (1 << SDA); //P3.0高电平,SDA高电平IIC RecvACK();  //等待应答信号
}

GetMPU6050Offset

/**************************************************************************************函数名称:GetMPU6050Offset*函数描述:获取g_MPUManager静态下传感器偏差*输   入:void*输   出:void*返   回:void*备   注:null**
*************************************************************************************/void GetMPU6050Offset(void) //校准
{int32_t buffer[6] = {0};int16_t i = 0;uint8_t k = 30;const int8_t MAX_GYRO_QUIET = 5;  //最大最小误差const int8_t MIN_GYRO_QUIET = -5;int16_t LastGyro[3] = {0};       //wait for calm downint16_t ErrorGyro[3] = {0};        //set offset initial to zeromemset(g_MPUManager.Offset,0,12);g_MPUManager.Offset[2] = 8192;    //根据手册量程设定加速度标定值while(k--)  //判断飞控是否处于静止状态{do{delay_ms(10);GetMPU6050Data();for(i=0; i<3; i++){ErrotGyro[i] = pMpu[I + 3] - LastGyro[i];LastGyro[i] = pMpu[i + 3];}}while((ErrorGyro[0] > MAX_GYRO_QUIET)|| (ErrorGyro[0] < MIN_GYRO_QUIET)|| (ErrorGyro[1] > MAX_GYRO_QUIET)|| (ErrorGyro[1] < MIN_GYRO_QUIET)|| (ErrorGyro[2] > MAX_GYRO_QUIET)|| (ErrorGyro[2] < MIN_GYRO_QUIET));//在误差范围内,认为静止的,退出循环,不在的话则是运动的,死循环}for(i=0; i<356; i++) //取第100到第356组的平均值作为校准值{}
}

GetMPU6050Data

/**************************************************************************************函数名称:GetMPU6050Data*函数描述:读取陀螺仪和加速度计的数据并做滤波处理*输   入:void*输   出:void*返   回:void*备   注:null**
*************************************************************************************/void GetMPU6050Data(void)
{uint8_t buffer[12];const float factor = 0.15f;   //滤波因素static float tBuff[3] = {0};static EKF_Filter_t s_EKF[3] = {{0.02, 0, 0, 0, 0.001, 0.543},{0.02, 0, 0, 0, 0.001, 0.543},{0.02, 0, 0, 0, 0.001, 0.543}};Acc_Read(buffer);Gyro_Read(buffer);for(int i=0; i<6; i++)  //将buffer中的高八位和低八位合起来{pMpu[i] = (((int16_t)buffer[i << 1] << 8) | buffer[(i << 1) + 1])  //- g_MPUManager.Offset[i];//此处对加速度做一维卡尔曼滤波if(i<3){KalmanFilter(&s_EKF[i],(float)pMpu[i]);  //一维卡尔曼pMpu[i] = (int16_t)s_EKF[i].out;}//此处对角速度做一阶低通滤波if(i>2){uint8_t k = i - 3;pMpu[i] = (int16_t)(tBuff[k] * (1 - factor) + pMpu[i] * factor);tBuff[k] = tBuff[k] * (1 - factor) + pMpu[i] * factor;}}
}
//私有变量区
MPU6050Manager_t  g_MPUManager;   //g_MPUManager原始数据
int16_t *pMpu = (int16_t *)&g_MPUManager;

MPU6050Manager_t结构体

typedef struct
{int16_t accX;  int16_t accY;  int16_t accZ;  int16_t gyroX;  int16_t gyroY;  int16_t gyroZ;  int16_t Offset[6];  bool Check;}MPU6050Manager_t;

##Acc_Read

/**************************************************************************************函数名称:Acc_Read*函数描述:获取加速度值*输   入:uint8_t *ptr ,写入地址*输   出:void*返   回:void*备   注:null**
*************************************************************************************/void Acc_Read(uint8_t *ptr)
{for(int i=0; i<6; i++){//0xD0,就是MPU6050从机地址ptr[i] = I2C_Read_Byte(0xD0,0x3B+i);}
}

##Gyro_Read

/**************************************************************************************函数名称:Gyro_Read*函数描述:获取陀螺仪值*输   入:uint8_t *ptr ,写入地址*输   出:void*返   回:void*备   注:null**
*************************************************************************************/void Gyro_Read(uint8_t *ptr)
{for(int i=0; i<6; i++){//0xD0,就是MPU6050从机地址ptr[i+6] = I2C_Read_Byte(0xD0,0x43+i);}
}

I2C总线读取MPU6050相关推荐

  1. 基于I2C总线的MPU6050学习笔记

    MPU6050学习笔记 1. 简述 一直想自己做个四轴飞行器,却无从下手,终于狠下决心,拿出尘封已久的MPU6050模块,开始摸索着数据手册分析,一步一步地实现了MPU6050模块的功能,从MPU60 ...

  2. ESP-Drone四旋翼无人机控制板上的MPU6050陀螺仪芯片I2C总线测试

    1.摘要 一款新的控制板卡在第一次使用时,都需要进行硬件功能的测试,以确保所有的硬件都能够正常工作后,才可以进入后续的软件编程阶段,ESP-Drone四旋翼无人机的控制板使用了mpu6050陀螺仪芯片 ...

  3. 实践 基于 Arduino I2C读取 MPU6050 三轴陀螺仪数据

    一.Arduino与MPU-6050的接线 六轴传感器模块MPU6050连线在Arduino UNO板子上,SDA接口对应的是A4引脚,SCL对应的是A5引脚.MPU6050需要5V的电源,可由UNO ...

  4. 【Renesas RA6M4开发板之I2C读取mpu6050】

    [Renesas RA6M4开发板之I2C读取mpu6050] 1.0 mpu6050 1.1 mpu6050介绍 1.2 mpu6050特点 1.3 mpu6050应用 2. RT-theard配置 ...

  5. GY906 MLX90614 非接触式 红外测温传感器 LabVIEW i2c总线数据读取

    GY906使用的红外测温芯片为MLX90614. 使用LabVIEW读取i2c总线数据时,需要知道传感器的地址,出厂默认为0x5A.传感器地址支持自己修改,存放在芯片EEPROM的0x0E位置,可以通 ...

  6. 【STM32】I2C练习,HAL库读取MPU6050角度陀螺仪

    I2C练习 MPU6050简介 寄存器查询表格 STM32CubeMx配置 代码文件 mpu6050.h文件 mpu6050.c文件 main.c文件 总结 MPU6050简介 MPU-6000(60 ...

  7. IIC(I2C)总线设备地址,例如E2PROM、CH455G等器件应用

    文章目录 背景 I2C特点 IIC的物理层 IIC的协议层 a.数据的有效性 b.起始和结束条件 d.数据帧格式 地址格式(重点!!!) 实战寻址 E2PROM 注意 CH455G地址 注意 背景 I ...

  8. IIC通讯读取MPU6050

    江科大自化协学习记录,本实验利用IIC读取MPU6050数值,并且在OLED屏上显示 代码在最后面,笔者水平一般,各位凑合着看. 首先是OLED显示的代码,底层驱动来自江科大自化协. 链接就放在这里了 ...

  9. I2C接口读取MPU9250磁力数值

    一开始拿到芯片手册云里雾里,根本没有找到关于磁力数据的寄存器,结果上网一查才知道,这芯片竟然是个胶水芯片... MPU9250内部是MPU6050和AK8963两个芯片合并在一起的,感觉傻傻的. 内部 ...

最新文章

  1. ( Android-源代码分享)
  2. Unity 2D游戏开发快速入门第1章创建一个简单的2D游戏
  3. android studio zbar,Android Studio 0.2.6和ZBar项目设置
  4. Spring Cloud构建微服务架构:分布式服务跟踪(跟踪原理)
  5. JavaScript 异常处理
  6. 大数据之Linux常用命令
  7. VLAN之间ACL和VACL的区别
  8. java pdfreader去除水印_(最新)JAVA使用Icepdf 5.0.6 pro的PDF转图片去掉水印的方法...
  9. JZOJ 5602. 【NOI2018模拟3.26】Cti JZOJ 5057. 【GDSOI2017模拟4.13】炮塔
  10. iPhone开发之Rotation
  11. Unicode 编码解码
  12. 《Python程序设计开发宝典》第一波转发积攒活动中奖名单
  13. linux ora-00119,Linux oracle ORA-00119 和 ORA-00132
  14. poj 1656 Counting Black
  15. [Leetcode 每日精选](本周主题-股票) 714. 买卖股票的最佳时机含手续费
  16. 玻色量子CEO文凯博士出席GTIC 2022全球AI芯片峰会,解读光量子计算新进展
  17. Android性能优化之APK瘦身详解(瘦身73%)
  18. 线上展厅核心优势解析
  19. 什么是指针压缩?如何开启和关闭指针压缩?为什么要进行指针压缩?有哪些注意的地方?
  20. rundll32.exe和regsvr32.exe

热门文章

  1. Druid Monitor监控
  2. 互联网快讯:华虹虹芯基金正式发起成立;极米高性能投影产品获用户青睐;中国电信联手钉钉研发“天翼钉”
  3. [YOLOv7/YOLOv5系列算法改进NO.20]Involution新神经网络算子引入网络
  4. 机器学习(四):CART分类树(基础篇)
  5. 查看ubuntu系统的版本信息
  6. RSA算法和DH算法的区别
  7. Apollo使用篇 - Apollo客户端的使用
  8. MATLAB颜色的使用(转)
  9. 错误解决方案:FATAL: Error inserting cmemk (/lib/modules/2.6.37/kernel/drivers/dsp/cmemk.ko): Bad address
  10. GNS3-1.3.10的安装及配置