I2C总线读取MPU6050
文章目录
- 实验目的
- 实验步骤
- 实验分析
- 源码分析
- 主函数
- 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相关推荐
- 基于I2C总线的MPU6050学习笔记
MPU6050学习笔记 1. 简述 一直想自己做个四轴飞行器,却无从下手,终于狠下决心,拿出尘封已久的MPU6050模块,开始摸索着数据手册分析,一步一步地实现了MPU6050模块的功能,从MPU60 ...
- ESP-Drone四旋翼无人机控制板上的MPU6050陀螺仪芯片I2C总线测试
1.摘要 一款新的控制板卡在第一次使用时,都需要进行硬件功能的测试,以确保所有的硬件都能够正常工作后,才可以进入后续的软件编程阶段,ESP-Drone四旋翼无人机的控制板使用了mpu6050陀螺仪芯片 ...
- 实践 基于 Arduino I2C读取 MPU6050 三轴陀螺仪数据
一.Arduino与MPU-6050的接线 六轴传感器模块MPU6050连线在Arduino UNO板子上,SDA接口对应的是A4引脚,SCL对应的是A5引脚.MPU6050需要5V的电源,可由UNO ...
- 【Renesas RA6M4开发板之I2C读取mpu6050】
[Renesas RA6M4开发板之I2C读取mpu6050] 1.0 mpu6050 1.1 mpu6050介绍 1.2 mpu6050特点 1.3 mpu6050应用 2. RT-theard配置 ...
- GY906 MLX90614 非接触式 红外测温传感器 LabVIEW i2c总线数据读取
GY906使用的红外测温芯片为MLX90614. 使用LabVIEW读取i2c总线数据时,需要知道传感器的地址,出厂默认为0x5A.传感器地址支持自己修改,存放在芯片EEPROM的0x0E位置,可以通 ...
- 【STM32】I2C练习,HAL库读取MPU6050角度陀螺仪
I2C练习 MPU6050简介 寄存器查询表格 STM32CubeMx配置 代码文件 mpu6050.h文件 mpu6050.c文件 main.c文件 总结 MPU6050简介 MPU-6000(60 ...
- IIC(I2C)总线设备地址,例如E2PROM、CH455G等器件应用
文章目录 背景 I2C特点 IIC的物理层 IIC的协议层 a.数据的有效性 b.起始和结束条件 d.数据帧格式 地址格式(重点!!!) 实战寻址 E2PROM 注意 CH455G地址 注意 背景 I ...
- IIC通讯读取MPU6050
江科大自化协学习记录,本实验利用IIC读取MPU6050数值,并且在OLED屏上显示 代码在最后面,笔者水平一般,各位凑合着看. 首先是OLED显示的代码,底层驱动来自江科大自化协. 链接就放在这里了 ...
- I2C接口读取MPU9250磁力数值
一开始拿到芯片手册云里雾里,根本没有找到关于磁力数据的寄存器,结果上网一查才知道,这芯片竟然是个胶水芯片... MPU9250内部是MPU6050和AK8963两个芯片合并在一起的,感觉傻傻的. 内部 ...
最新文章
- ( Android-源代码分享)
- Unity 2D游戏开发快速入门第1章创建一个简单的2D游戏
- android studio zbar,Android Studio 0.2.6和ZBar项目设置
- Spring Cloud构建微服务架构:分布式服务跟踪(跟踪原理)
- JavaScript 异常处理
- 大数据之Linux常用命令
- VLAN之间ACL和VACL的区别
- java pdfreader去除水印_(最新)JAVA使用Icepdf 5.0.6 pro的PDF转图片去掉水印的方法...
- JZOJ 5602. 【NOI2018模拟3.26】Cti JZOJ 5057. 【GDSOI2017模拟4.13】炮塔
- iPhone开发之Rotation
- Unicode 编码解码
- 《Python程序设计开发宝典》第一波转发积攒活动中奖名单
- linux ora-00119,Linux oracle ORA-00119 和 ORA-00132
- poj 1656 Counting Black
- [Leetcode 每日精选](本周主题-股票) 714. 买卖股票的最佳时机含手续费
- 玻色量子CEO文凯博士出席GTIC 2022全球AI芯片峰会,解读光量子计算新进展
- Android性能优化之APK瘦身详解(瘦身73%)
- 线上展厅核心优势解析
- 什么是指针压缩?如何开启和关闭指针压缩?为什么要进行指针压缩?有哪些注意的地方?
- rundll32.exe和regsvr32.exe
热门文章
- Druid Monitor监控
- 互联网快讯:华虹虹芯基金正式发起成立;极米高性能投影产品获用户青睐;中国电信联手钉钉研发“天翼钉”
- [YOLOv7/YOLOv5系列算法改进NO.20]Involution新神经网络算子引入网络
- 机器学习(四):CART分类树(基础篇)
- 查看ubuntu系统的版本信息
- RSA算法和DH算法的区别
- Apollo使用篇 - Apollo客户端的使用
- MATLAB颜色的使用(转)
- 错误解决方案:FATAL: Error inserting cmemk (/lib/modules/2.6.37/kernel/drivers/dsp/cmemk.ko): Bad address
- GNS3-1.3.10的安装及配置