从IIC通信原理到使用 —— MPU6050
IIC通信详解 —— 基于MPU6050模块
从IIC通信原理到使用 —— MPU6050
IIC通信可以简单地理解成就是数据的通信,就是单片机(主机)与设备(从机)之间的一种通信协议,两者必须遵从这个协议才能正确的相互读写数据,它这个通信过程只要两根线就能给完成,分别是SCL(时钟线)和SDA(数据线);
这个主机与从机的关系一定要理解好,因为下一次不一定是单片机,有些从机也可以作为主机,可以先把主机理解成能够向其他设备发送指令/命令的一方,比如如果你作为主机,你是想读的时候才去读的,想写的时候就去写,比较主动;而如果你作为从机,这就由不得你,你只能听从主机的命令,主机说要读,你就要把数据给出去,主机说要写,你就得乖乖被写。
现在假设单片机作为主机,连接在SDA和SCL的两条线上的设备均是它的从机,比如下面图所示:
到这里我们已经能够有一个IIC主从设备的概念了,那么假如单片机想要通过IIC来读取从设备的信息应该都要做什么呢?也就是说,整个IIC通信过程应该是怎么样子实现的?
一、IIC通信协议
在解释之前,可以先知道一个这个协议不协议的到底是怎么实现的,打比喻说只有一个主机一个从机时,大家先定一个协议,如果某根线的电平怎么怎么样,同时另外一根线的电平又怎么怎么样的时候,对应的是要读?还是要写?还是其他什么?上面这个过程也就相当于主机发出的指令,从机通过两根线的电平状态来确定主机的指令是什么。(注意,不要简单地理解为 00 01 10 11 四种状态)。指令是通过两根线来发送,里面的数据也是通过那两根线,所以你至少要定义你什么时候是指令什么时候是数据吧?所以就会有协议这种东西。
IIC总线在传输数据的过程中一共有三种类型信号(指令),分别为:开始信号、结束信号和应答信号。这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。同时我们还要介绍其空闲状态、数据的有效性、数据传输。看到协议不要害怕,我们只需要先知道它内部的原理,至于怎么来实现,后面再看代码进行解释。
①. 空闲状态
当SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态。这种状态就相当于没有设备在占用通信通道,大家各自在自家互不搭理。正常情况下,当系统开始工作,如果主从不通信时就希望它是空闲状态,也就是说开机后默认是空闲状态,那么这两个高电平可以由上拉电阻来完成。
②. 开始信号
当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
③. 结束信号
当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。
④. 应答信号
发射器 定义要发送数据的一端为发射器,当主机往从机写命令时,可以理解成主机作为发射器,当主机读取从机数据时,可以理解成从机往主机写数据,这时候从机就是发射器;
实现过程 发送器每发送一个字节(1byte = 8bit),8个时钟脉冲用来储存数据内容,在第9个时钟脉冲释放数据线,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
⑤. 数据的有效性
在数据传送时,SCL为高电平期间,SDA上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。 即:数据在SCL的上升沿到来之前就需准备好。并在在下降沿到来之前必须稳定。
以上就是协议的一些内容,在发送数据时必须得遵守协议,开启读取、读取完成之后一定要发送停止信号来释放总线。我们可以接着看数据的发送过程是怎么实现的。
二、通过IIC协议实现收发
因为在总线上可能会有很多从设备,不止一个,所以主机在发送或者接受数据的时候,必须要知道从机的设备地址(不同设备有自己不同的设备物理地址),相当于如果你要去某个人的家,至少你要先知道他们家的地址。
知道了这个物理地址后,也就相当于主机能在众多从设备中找到了想要找的从设备,但是一个完整设备意味着它有自己的芯片,有自己的储存单元,所以主机不仅仅只是要找到这个设备,还要找到该设备里的主机想要读写的存储单元(寄存器),相当于你要去某个人的家找一个人,你到了他家之后,还要在他众多的家人中找到你要找的那个人。
当主机确定了从机设备、从机设备的寄存器,就能往里面进行读写数据了,而这个读写数据的过程就必须得按照这个IIC协议来完成,这么说可能还比较抽象。下面先介绍MPU6050,再结合IIC来实现单片机从MPU6050读取数据。
三、MPU6050的介绍
MPU-60X0由以下几个关键块和功能组成
1、带有16位ADC和信号调理的三轴MEMS速率陀螺仪传感器
2、具有16位ADC和信号调理的三轴MEMS加速度传感器
3、数字运动处理器(DMP)引擎
4、传感器数据寄存器
5、FIFO
6、中断
7、数字输出温度传感器
首先要知道6050的内置模块。包括一个三轴MEMS(微机电系统(MEMS, Micro-Electro-Mechanical System))陀螺仪、三轴MEMS加速度计,一个数字运动处理引擎(DMP)、还有用于第三方数字传感器接口的辅助IIC端口,(GY-521上面的xda,xcl),常用于扩展磁力计,当辅助IIC接口连接到一个三轴磁力计上面时,6050能提供一个完整的九轴融合输出到其主IIC接口上。同时,6050内部还内置了一个可编程的低通滤波器,可用于传感器数据的滤波。
系统结构图
通过系统结构图只需要你大概知道有什么在里面就行了。
接线图
当不使用磁力计时(使用磁力计时,MPU6050作为主机去读取磁力计的数据,然后再以从机的身份向单片机主机发送加速度、陀螺仪和从磁力计读取的数据),只需要接电源线(5V)、地线、SCL和SDA即可,其他引脚均闲空。
关键功能介绍
① 带有16位ADC和信号调理的三轴MEMS陀螺仪
MPU-60X0由三个独立的振动MEMS速率陀螺仪组成,可检测旋转角度X轴,Y轴和Z轴。 当陀螺仪围绕任何感应轴旋转时,科里奥利效应就会产生电容式传感器检测到的振动。 所得到的信号被放大,解调和滤波产生与角速度成比例的电压。 该电压使用单独的片内数字化16位模数转换器(ADC)对每个轴进行采样。 陀螺仪传感器可以全面范围的被数字编程为每秒±250,±500,±1000或±2000度(dps)。 ADC样本速率可以从每秒8,000个采样点编程到每秒3.9个采样点,并且可由用户选择低通滤波器可实现广泛的截止频率。
这就是指模块内部自带了陀螺仪,经其内部的数模转换器可以将陀螺仪的模拟量转成可传输的数字量,并且存储在16位寄存器里(由两个8位寄存器组成),关于获取陀螺仪数据时,只需直接从对应的寄存器里读出数据即可,注意此时的数据并非是倾角。
简而言之,陀螺仪就是角速度检测仪。比如,一块板,以X轴为轴心,在一秒钟的时间转到了90度,那么它在X轴上的角速度就是 90度/秒 (DPS, 角速度单位,Degree Per Second的缩写°/S ,体现了转动的快慢)
② 具有16位ADC和信号调理的三轴MEMS加速度计
MPU-60X0的3轴加速度计为每个轴使用单独的检测质量。 加速沿着一条特定轴在相应的检测质量上引起位移,并且电容式传感器检测到该位移位移有差别。 MPU-60X0的架构降低了加速度计的敏感度制造变化以及热漂移。 当设备放置在平坦的表面上时,将进行测量在X和Y轴上为 0g,在Z轴上为+ 1g。 加速度计的比例因子在工厂进行校准并且在名义上与电源电压无关。 每个传感器都有一个专用的sigma-delta ADC来提供数字输出。 数字输出的满量程范围可以调整到±2g,±4g,±8g或±16g。
总而言这,加速度传感器,其实是力传感器。用来检查上下左右前后哪几个面都受了多少力(包括重力),然后计算角度。
③ 数字运动处理器(DMP)
DMP就是指MPU6050内部集成的处理单元,可以直接运算出四元数和姿态,而不再需要另外进行数学运算。四元数就是4个数,可以表征姿态,经过几个数学公式之后就可以的出姿态,姿态包括pitch,roll,yaw。DMP的使用大大简化了代码设计,可想而知mpu9150(mpu6050)并不单单是一款传感器,其内部还包含了可以独立完成姿态解算算法的处理单元。
由DMP实现姿态解算算法将单片机从算法处理的压力中解放出来,单片机所要做的是等待DMP解算完成后产生的外部中断,在外部中断里去读取姿态解算的结果。这样单片机有大量的时间来处理其他任务,提高了系统的实时性。综上,dmp之后直接出结果,可以直接用,当然你如果有特殊需要自己还要加滤波也没有问题。
但是听说DMP的参考平面有点蛋疼。他解算出来的姿态角是以上电时的平面为基准平面的。也就是说每次上电都要把装置摆到绝对水平。但这有点困难。
④ 传感器数据寄存器
传感器数据寄存器包含最新的陀螺仪,加速度计,辅助传感器和温度测量数据。 它们是只读寄存器,可通过串行接口访问。 这些寄存器的数据可以随时读取。 但是,可以使用中断函数来确定新数据何时可用。
存储这些数据的寄存器均只是可读状态,称之为数据寄存器,注意:关于陀螺仪和加速度的寄存器均是16位的,也就是说在读取他们数据时,需要知道加速度/陀螺仪对应的两个寄存器的内部地址,并且读取出来的数据需要通过转换合成。
上图是陀螺仪数据寄存器,通过读取这6个寄存器,就可以读到陀螺仪 x/y/z 轴的值,比如 x 轴的数据,可以通过读取 0X43(高 8 位)和 0X44(低 8 位)寄存器得到,其他轴以此类推。
上图是加速度数据寄存器,通过读取这6个寄存器,就可以读到加速度传感器 x/y/z 轴的值,比如读 x 轴的数据,可以通过读取 0X3B(高 8 位)和0X3C(低8位)寄存器得到,其他轴以此类推。
⑤ 关于其他寄存器的设置及介绍
我是从这篇帖子里学习的,我已经码出来分享给大家
--------》 传送门
知道以上寄存器很重要,要知道寄存器每个位什么值对应着什么样的功能,还要知道其对应的内存地址,以供主机进行寻找。
⑥ FIFO缓冲器
MPU-60X0包含一个可通过串行接口访问的1024字节FIFO寄存器。 FIFO配置寄存器决定哪个数据写入FIFO。 可能的选择包括陀螺仪数据,加速计数据,温度读数,辅助传感器读数和 FSYNC 输入。 FIFO 计数器跟踪 FIFO 中包含的有效数据字节数。 FIFO寄存器支持突发读取。 中断功能可用于确定新数据何时可用。
⑦ 中断
中断功能通过中断配置寄存器进行配置。 可配置的项目包括INT引脚配置,中断锁存和清除方法以及中断触发器。 可触发中断的项目有:
(1)时钟发生器锁定到新的参考振荡器(用于切换时钟源);
(2)可以读取新数据(来自FIFO和数据寄存器);
(3)加速度计事件中断;
(4)MPU-60X0 没有收到辅助传感器的确认I2C总线。
中断状态可以从中断状态寄存器读取。
至此,了解了MPU6050的一些基础知识后,我们就可以通过代码建立IIC通信,让单片机与MPU6050进行通信。
四、单片机与MPU6050的IIC实现
在贴代码之前,需要明确以下几点:
A. 关于地址
---- 从设备的地址是用7bit来表示的,但是一个寄存器里有8个位,所以最终这个设备的地址是由已知的7位和第8位组成,那么第8位到底是什么呢?
规定 :在IIC通信开始发送一帧数据时,前面7bit是设备或者寄存器的地址,第8位则是读或者写的方向命令位,0为写命令,1为读命令。
就比如从官方所给资料来看,MPU6050的地址是0x68或者0x69,拿0x68举例,其表示如下:
7bit | 6bit | 5bit | 4bit | 3bit | 2bit | 1bit | 0bit |
---|---|---|---|---|---|---|---|
1 | 1 | 0 | 1 | 0 | 0 | 0 | AD0 |
前面7位(110 1000)构成从设备的地址0x68,而最后一位是未知的,或者说,是由用户自己定义设置的(AD0引脚),比如如果在MPU6050模块的AD0引脚接地,则最后一位表示0,那么加进去以后,地址就变成了1101 0000,转换成十六进制也就是0xD0,此处也代表写命令。
所以以后在主机寻找MPU6050这个设备时,需要写入一帧数据以表示寻找从机,这一帧数据就是0xD0,说明白点,0xD0是由设备物理地址+命令来构成最终的“门牌”,主机以后就是通过这个门牌来找到MPU6050,主机只要把“门牌”发送出去,系统的状态就代表着主机向从机写数据,一直持续到停止信号。
与设备物理地址不同,设备内部的寄存器地址是由8位构成,因此只需要在开启信号发起时,发送寻找MPU6050的“门牌”(相当于告诉了设备主机打算写入数据,只要还没有停止信号就代表后面的操作一直都是写信号),接着就可以继续发送寄存器的内存地址(8位地址,最后一位不再是表示读写命令,因为停止信号还没到来,所以状态一直是写的命令)。
B. 关于通信过程
主机写数据给从机时,先“广播”从机地址(相当于找到对应从机),再发送从机内部寄存器的地址(相当于找到对应从机的对应寄存器),然后主机再发送数据到该寄存器,主机发送完一字节数据后,从机需要发出一个应答信号(这个过程是从机把应答信号发送至主机的CY位)来告诉主机已接收完成一帧数据。
主机读从机数据时,要先"广播"从机地址,再发送从机内部寄存器的地址(相当于要找到数据的来源),然后直接读取一字节数据,读取完一字节数据后,主机向从机发送应答信号(相当于主机告诉从机已经读取到一字节)
综上,不管是从机还是主机,只要是被写入数据,当被写入完一字节数据时,都需要向对方发送应答信号。(相当于读别人的数据,这个过程比如:可以把主机给从机写数据的过程理解成从机读取主机的数据,同样,主机读取从机数据时可以理解成从机往主机里些数据)
代码实现及注释
STC89C52 + MPU6050 + LCD1602
.
// 功能: 显示加速度计和陀螺仪的10位原始数据
//****************************************
// 晶振:11.0592M
// 显示:LCD1602#include <REG52.H>
#include <math.h> //Keil library
#include <stdio.h> //Keil library
#include <INTRINS.H> //这个库需要_nop_()函数typedef unsigned char uchar; //类型定义
typedef unsigned short ushort;
typedef unsigned int uint;#define DataPort P0 //LCD1602数据端口
sbit SCL=P1^0; //IIC时钟引脚定义
sbit SDA=P1^1; //IIC数据引脚定义
sbit LCM_RS=P2^0; //LCD1602命令端口
sbit LCM_RW=P2^1; //LCD1602命令端口
sbit LCM_EN=P2^2; //LCD1602命令端口
uchar dis[4]; //显示数字(-511至512)的字符数组
int dis_data; //变量//看以下变量的时候对应着寄存器里面名称,容易有印象
#define SMPLRT_DIV 0x19 //陀螺仪采样率,典型值:0x07(125Hz)
#define CONFIG 0x1A //低通滤波频率,典型值:0x06(5Hz)
#define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
#define ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
#define ACCEL_XOUT_H 0x3B //X轴加速度数据寄存器1地址
#define ACCEL_XOUT_L 0x3C //X轴加速度数据寄存器2地址
#define ACCEL_YOUT_H 0x3D //Y轴加速度数据寄存器1地址
#define ACCEL_YOUT_L 0x3E //Y轴加速度数据寄存器2地址
#define ACCEL_ZOUT_H 0x3F //Z轴加速度数据寄存器1地址
#define ACCEL_ZOUT_L 0x40 //Z轴加速度数据寄存器2地址
#define TEMP_OUT_H 0x41 //温度传感器数据寄存器1地址
#define TEMP_OUT_L 0x42 //温度传感器数据寄存器2地址
#define GYRO_XOUT_H 0x43 //X轴陀螺仪数据寄存器1地址
#define GYRO_XOUT_L 0x44 //X轴陀螺仪数据寄存器2地址
#define GYRO_YOUT_H 0x45 //Y轴陀螺仪数据寄存器1地址
#define GYRO_YOUT_L 0x46 //Y轴陀螺仪数据寄存器2地址
#define GYRO_ZOUT_H 0x47 //Z轴陀螺仪数据寄存器1地址
#define GYRO_ZOUT_L 0x48 //Z轴陀螺仪数据寄存器2地址
#define PWR_MGMT_1 0x6B //电源管理,典型值:0x00(正常启用)
#define SlaveAddress 0xD0 //IIC写入时的地址字节数据,+1为读取
//#define WHO_AM_I 0x75 //IIC地址寄存器(默认数值0x68,只读)//****************************************
//函数声明
//****************************************
void delay(unsigned int k); //延时
void InitLcd(); //初始化lcd1602
void lcd_printf(uchar *s,int temp_data); //把整数转成字符串
void WriteDataLCM(uchar dataW); //向LCD写入数据
void WriteCommandLCM(uchar CMD,uchar Attribc); //LCD指令
void DisplayOneChar(uchar X,uchar Y,uchar DData); //显示一个字符
void DisplayListChar(uchar X,uchar Y,uchar *DData,L); //显示字符串
void InitMPU6050(); //初始化MPU6050
void Delay5us(); //IIC协议用到的一些延迟
void I2C_Start(); //开始信号
void I2C_Stop(); //停止信号
void I2C_SendACK(bit ack); //单片机向MPU6050发送应答
bit I2C_RecvACK(); //单片机接收MPU6050应答
void I2C_SendByte(uchar dat); //通过IIC,单片机向从机发送一字节数据
uchar I2C_RecvByte(); //通过IIC,单片机接收从机一字节数据
void I2C_ReadPage();
void I2C_WritePage();
void display_ACCEL_x(); //LCD显示X轴加速度信息
void display_ACCEL_y(); //LCD显示Y轴加速度信息
void display_ACCEL_z(); //LCD显示Z轴加速度信息
uchar Single_ReadI2C(uchar REG_Address); //读取I2C数据
void Single_WriteI2C(uchar REG_Address,uchar REG_data); //向I2C写入数据//****************************************
//lcd相关
//****************************************
void lcd_printf(uchar *s,int temp_data) //整数转字符串
{if(temp_data<0){temp_data=-temp_data;*s='-';}else *s=' ';*++s =temp_data/100+0x30;temp_data=temp_data%100; //取余运算*++s =temp_data/10+0x30; //转成ASCII码temp_data=temp_data%10; //取余运算*++s =temp_data+0x30;
}void delay(unsigned int k) //延迟函数
{ unsigned int i,j; for(i=0;i<k;i++){ for(j=0;j<121;j++);}
}void WaitForEnable(void) //LCD1602写允许
{ DataPort=0xff; LCM_RS=0;LCM_RW=1;_nop_();LCM_EN=1;_nop_();_nop_();while(DataPort&0x80); LCM_EN=0;
} void WriteCommandLCM(uchar CMD,uchar Attribc) //LCD1602写入命令
{ if(Attribc)WaitForEnable(); LCM_RS=0;LCM_RW=0;_nop_();DataPort=CMD;_nop_(); LCM_EN=1;_nop_();_nop_();LCM_EN=0;
} void WriteDataLCM(uchar dataW) //LCD1602写入数据
{ WaitForEnable(); LCM_RS=1;LCM_RW=0;_nop_();DataPort=dataW;_nop_(); LCM_EN=1;_nop_();_nop_();LCM_EN=0;
}void DisplayOneChar(uchar X,uchar Y,uchar DData) //LCD1602写入一个字符
{ Y&=1; X&=15; if(Y)X|=0x40; X|=0x80; WriteCommandLCM(X,0); WriteDataLCM(DData);
} void DisplayListChar(uchar X,uchar Y,uchar *DData,L) //LCD1602显示字符串
{uchar ListLength=0; Y&=0x1; X&=0xF; while(L--) { DisplayOneChar(X,Y,DData[ListLength]);ListLength++; X++; }
}void InitLcd() //LCD1602初始化
{ WriteCommandLCM(0x38,1); //设置8位格式,2行,5x7 WriteCommandLCM(0x08,1); //关闭显示,检测忙信号 WriteCommandLCM(0x01,1); //清除屏幕显示 WriteCommandLCM(0x06,1); //设定输入方式,增量不移位 WriteCommandLCM(0x0c,1); //整体显示,关光标,不闪烁DisplayOneChar(0,0,'A'); //显示A字符在第0行第0位DisplayOneChar(0,1,'G'); //总共有0,1两行,每行0~15个字符
} //****************************************
//IIC相关
//****************************************
void Delay5us() //延时5微秒(STC90C52RC@12M)
{_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
}void I2C_Start() //I2C起始信号
{SDA = 1; //拉高数据线SCL = 1; //拉高时钟线Delay5us(); //延时SDA = 0; //产生下降沿Delay5us(); //延时SCL = 0; //拉低时钟线
}void I2C_Stop() //I2C停止信号
{SDA = 0; //拉低数据线SCL = 1; //拉高时钟线Delay5us(); //延时SDA = 1; //产生上升沿Delay5us(); //延时
}void I2C_SendACK(bit ack) //I2C发送应答信号,(0:ACK 1:NAK)
{SDA = ack; //写应答信号SCL = 1; //拉高时钟线Delay5us(); //延时SCL = 0; //拉低时钟线Delay5us(); //延时
}bit I2C_RecvACK() //I2C接收应答信号
{SCL = 1; //拉高时钟线Delay5us(); //延时CY = SDA; //读应答信号,存在CY进位位SCL = 0; //拉低时钟线Delay5us(); //延时return CY;
}void I2C_SendByte(uchar dat) //向I2C总线发送一个字节数据
{uchar i;for (i=0; i<8; i++) //8位计数器{dat <<= 1; //移出数据的最高位SDA = CY; //送数据口SCL = 1; //拉高时钟线Delay5us(); //延时SCL = 0; //拉低时钟线Delay5us(); //延时}I2C_RecvACK();
}uchar I2C_RecvByte() //从I2C总线接收一个字节数据
{uchar i;uchar dat = 0;SDA = 1; //使能内部上拉,准备读取数据,for (i=0; i<8; i++) //8位计数器{dat <<= 1;SCL = 1; //拉高时钟线Delay5us(); //延时dat |= SDA; //读数据 SCL = 0; //拉低时钟线Delay5us(); //延时}return dat;
}void Single_WriteI2C(uchar REG_Address,uchar REG_data)//向I2C设备写入一个字节数据
{I2C_Start(); //起始信号I2C_SendByte(SlaveAddress); //发送设备地址+写信号I2C_SendByte(REG_Address); //内部寄存器地址,这里的写信号由上面一行得来I2C_SendByte(REG_data); //内部寄存器数据,I2C_Stop(); //发送停止信号,持续到停止信号
}uchar Single_ReadI2C(uchar REG_Address)//从I2C设备读取一个字节数据
{uchar REG_data;I2C_Start(); //起始信号I2C_SendByte(SlaveAddress); //发送设备地址+写信号I2C_SendByte(REG_Address); //发送存储单元地址,从0开始//上面先进行写命令(广播),找到寄存器位置先(数据的来源) I2C_Start(); //起始信号I2C_SendByte(SlaveAddress+1); //发送设备地址+读信号REG_data=I2C_RecvByte(); //读出寄存器数据I2C_SendACK(1); //向从机发送应答信号I2C_Stop(); //停止信号return REG_data;
}void InitMPU6050() //初始化MPU6050
{Single_WriteI2C(PWR_MGMT_1, 0x00); //解除休眠状态Single_WriteI2C(SMPLRT_DIV, 0x07); //设置陀螺仪采样率,典型值:0x07(125Hz)Single_WriteI2C(CONFIG, 0x06); //低通滤波频率,典型值:0x06(5Hz)Single_WriteI2C(GYRO_CONFIG, 0x18); //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)Single_WriteI2C(ACCEL_CONFIG, 0x01);//加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
}//****************************************
//主程序相关
//****************************************
int GetData(uchar REG_Address) //将MPU6050内部的两个数据寄存器的数据进行合成
{char H,L;H=Single_ReadI2C(REG_Address);L=Single_ReadI2C(REG_Address+1);return (H<<8)+L; //合成数据,返回十六进制数
}void Display10BitData(int value,uchar x,uchar y)//在1602上显示10位数据
{value /= 64; //转换为10位数据lcd_printf(dis, value); //转换数据显示,dis是dis[4]数组的头地址DisplayListChar(x,y,dis,4); //启始列,行,显示数组,显示长度
}void main()
{ delay(500); //上电延时 InitLcd(); //液晶初始化InitMPU6050(); //初始化MPU6050delay(150);while(1){Display10BitData(GetData(ACCEL_XOUT_H),2,0); //显示X轴加速度,第0行第2列Display10BitData(GetData(ACCEL_YOUT_H),7,0); //显示Y轴加速度Display10BitData(GetData(ACCEL_ZOUT_H),12,0); //显示Z轴加速度Display10BitData(GetData(GYRO_XOUT_H),2,1); //显示X轴角速度Display10BitData(GetData(GYRO_YOUT_H),7,1); //显示Y轴角速度Display10BitData(GetData(GYRO_ZOUT_H),12,1); //显示Z轴角速度delay(500);}
}
直接复制以上代码,即可成功运行。
如有理解错误,往大家多多指正,谢谢!
从IIC通信原理到使用 —— MPU6050相关推荐
- iic通信原理_电子知识之IIC通信原理和协议分享
IIC 的一些特征: 两条总线:串行数据总线(SDA)和串行时钟总线(SCL) 真正的多主机总线 连接到相同总线的ic数量只受到总线的最大电容400pF限制. 串行8位双向数据在标准模式下可达100K ...
- STM32CubMX自学笔记(十)---IIC通信实验
STM32CubMX自学笔记(十)-IIC通信实验 I2C通信协议的简介 引脚少,硬件实现简单,可扩展性强,不需要外部收发设备,广泛用在多个集成电路通信. 物理层特点: 信号线SDA和时钟线SCL 1 ...
- 学习记录--陀螺仪模块(MPU6050:IIC通信,us延时函数)
一,mpu6050模块基础(参考HAL库开发指南) 二,CUBEMX配置 用模拟IIC,只需要打开一个串口打印数据就行,IO口的配置直接写在板级支持包的init里了 三,keil中代码(参考正点原子与 ...
- [转]从IIC实测波形入手,搞懂IIC通信
(转载请删除括号里的内容) 玩单片机的朋友都知道IIC通信这个工具,但好多人只是会用,内部的原理不求甚解,或是想要了解其原理,但却对抽象的时序描述一头雾水.本文将从实测的IIC波形入手,带你看到真实的 ...
- STM32 TM1637驱动数码管 IIC通信
最近在做iic实验的过程中发现手边刚好有一个数码管他的驱动正好是使用iic,话不多说直接上代码了 这里就不赘述iic通信的原理和时序图了,网上相关资源也很多这里就附一篇iic的文章,这篇文章相当详细. ...
- 51单片机开发板模拟实现IIC通信
51单片机模拟实现IIC通信 IIC.h IIC.c main.c 总结 IIC.h #ifndef _iic_h_ #define _iic_h_ #include <reg52.h> ...
- STM32 PAJ7620U2手势识别模块(IIC通信)程序源码详解
最近在自学设计下基于STM32单片机的项目,想用手势识别模块做一点好玩的,做个手势控制家居设备开关,另外正好借此巩固I²C 通信.因此,我想借这个机会在这里和大家分享一下自己学习STM32单片机时的所 ...
- 软件IIC通信以及源码解析(如何使用)
以对读取MPU6050为例,解析如何采用IIC通信源码. IIC的的通信,通常三种用途读写.分为: 1: 2: 3: 注:其中最常用的就是1和3了. 对1进行讲解: 指定地址写,通常用作对状态机模块的 ...
- STC12C5A60S2使用模拟IIC通信与AT24C02芯片编程
文章目录 一.前言 二.IIC通讯详解 2-1.IC协议简介 2-2.常用的IIC通讯设备 2-3.IIC物理层特点 2-4.IIC协议层特点 2-4-1.IIC基本读写过程 2-4-2.通讯起始和停 ...
最新文章
- 微信小程序 解决请求服务器手机预览请求不到数据的方法
- 结构损伤检测与智能诊断 陈长征_阜康危房检测价格
- python - 配置文件
- python pip 升级
- 微信小程序之通过Canvas生成图片保存到手机相册
- python Binary I/O
- C#學習基礎------事件和索引指示器
- 计算机上机单招试题及答案,全国高职单招计算机类模拟试卷考卷及答案
- C++实现 逆波兰表达式计算问题
- 第68天-内网安全-域横向 PTHPTKPTT 哈希票据传
- win10浏览器加载很慢_Win10 IE浏览器的网页加载速度很慢总是卡死怎么办
- 使用python lxml库中的xpath、etree爬取网页超链接
- Latex去掉proof后面显示的小白框 (\qed)
- core dumped 错误
- 乙女心,养的第一株多肉小植物
- visual basic 6 下载 和 Vb6sp6 下载
- python 人像素描_谁说程序员不懂浪漫的,直接用 Python 给女朋友画张素描
- YOLOv4论文中文翻译
- excel切片器_Excel切片器,让图表动起来
- 机器学习之线性回归原理详解、公式推导(手推)、简单实例