从IIC通信原理到使用 —— MPU6050

本文详细介绍了IIC通信协议,包括开始信号、结束信号和应答信号等,并以MPU6050为例,讲解了如何通过IIC协议实现单片机与传感器的通信。内容涵盖MPU6050的内部结构、功能和寄存器介绍,以及单片机如何通过代码实现IIC通信与数据读取。
摘要由CSDN通过智能技术生成

IIC通信详解 —— 基于MPU6050模块

从IIC通信原理到使用 —— MPU6050

IIC通信可以简单地理解成就是数据的通信,就是单片机(主机)与设备(从机)之间的一种通信协议,两者必须遵从这个协议才能正确的相互读写数据,它这个通信过程只要两根线就能给完成,分别是SCL(时钟线)和SDA(数据线);

这个主机与从机的关系一定要理解好,因为下一次不一定是单片机,有些从机也可以作为主机,可以先把主机理解成能够向其他设备发送指令/命令的一方,比如如果你作为主机,你是想读的时候才去读的,想写的时候就去写,比较主动;而如果你作为从机,这就由不得你,你只能听从主机的命令,主机说要读,你就要把数据给出去,主机说要写,你就得乖乖被写

现在假设单片机作为主机,连接在SDA和SCL的两条线上的设备均是它的从机,比如下面图所示:
主从直接的IIC连线示意图
到这里我们已经能够有一个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];
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值