一、实物图(型号:MPU6050)
二、原理图
编号 | 名称 | 功能 |
1 | VCC | 电源正 |
2 | GND | 电源地 |
3 | SCL | 串行时钟输入 |
4 | SDA | 串行地址和数据输入/输出 |
5 | XDA | 外部从设备串行地址和数据输入/输出 |
6 | XCL | 外部从设备串行时钟输入 |
7 | AD0 | IIC地址控制引脚(接GND,地址为0X68,接VCC,地址为0X69) |
8 | INT | 中断引脚 |
三、简介
MPU6050是一个6轴运动处理传感器。它集成了3轴MEMS陀螺仪,3轴MEMS加速度计,以及一个可扩展的数字运动处理器DMP(Digital Motion Processor),可用外部IIC接口连接一个第三方的数字传感器,比如磁力计,扩展之后就可以输出一个9轴信号。
MPU6050对陀螺仪和加速度计分别用了三个16位ADC,将其测量的模拟量转化为可输出的数字量。为了精确跟踪快速和慢速的运动,传感器的测量范围都是用户可控的。
陀螺仪的可测范围为±250,±500,±1000,±2000°/秒(dps),加速度计可测范围为±2,±4,±8,±16g。
四、内部框图
其中,SCL 和 SDA 是连接 MCU 的 IIC 接口,MCU 通过这个 IIC 接口来控制 MPU6050, 另外还有一个 IIC 接口:AUX_CL 和 AUX_DA,这个接口可用来连接外部从设备,比如磁 传感器,这样就可以组成一个九轴传感器。VLOGIC 是 IO 口电压,该引脚最低可以到 1.8V, 我们一般直接接 VDD 即可。AD0 是从 IIC 接口(接 MCU)的地址控制引脚,该引脚控制 IIC 地址的最低位。如果接 GND,则 MPU6050 的 IIC 地址是:0X68,如果接 VDD,则是
0X69,注意:这里的地址是不包含数据传输的最低位的(最低位用来表示读写)
五、通信协议(I2C通信)
1、I2C总线介绍
<1>I2C总线(Inter IC bus)是由Philips公司开发的一种通用数据总线。
<2>两根通信线:SCL(Serial Clock串行时钟线)、SDA(Serial Data串行数据线)。
<3>同步、半双工,带数据应答。
*注:同步(因为它有单独的时钟线)、半双工(SDA只有一根线,并且还要来回通信)
<4>通用的I2C总线,可以使各种设备的通信标准统一,对于厂家来说,使用成熟的方案可以缩短芯片设计周期、提高稳定性,对于应用者来说,使用通用的通信协议可以避免学习各种各样的自定义协议,降低了学习和应用的难度。
2、I2C电路规范
<1>所有I2C设备的SCL连在一起,SDA连在一起
<2>设备的SCL和SDA均要配置成开漏输出模式(硬件IIC)
*开漏输出模式——断开时引脚成浮空状态(电路断开,电压不稳定)
<3>SCL和SDA各添加一个上拉电阻,阻值一般为4.7K~10K左右
<4>开漏输出和上拉电阻的共同作用实现了“线与”的功能,此设计主要是为了解决多机通信互相干扰的问题。
3、时序结构
起始信号:SCL高电平期间,SDA从高电平切换到低电平
停止信号:SCL高电平期间,SDA从低电平切换到高电平
代码如下:
/****
*******I2C总线启动信号
*****/
void MPU6050_IIC_Start(void)
{
MPU6050_SDA = 1;
MPU6050_SCL = 1;
MPU6050_IIC_Delay(DELAY_TIME);
MPU6050_SDA = 0;
MPU6050_IIC_Delay(DELAY_TIME);
MPU6050_SCL = 0;
}
/****
*******I2C总线停止信号
*****/
void MPU6050_IIC_Stop(void)
{
MPU6050_SDA = 0;
MPU6050_SCL = 1;
MPU6050_IIC_Delay(DELAY_TIME);
MPU6050_SDA = 1;
MPU6050_IIC_Delay(DELAY_TIME);
}
发送应答:在接收完一个字节之后,主机在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答。
接收应答:在发送完一个字节之后,主机在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)。
代码如下:
/****
*******发送应答或非应答信号
*****/
void MPU6050_IIC_SendAck(bit ackbit)
{
MPU6050_SCL = 0;
MPU6050_SDA = ackbit;
MPU6050_IIC_Delay(DELAY_TIME);
MPU6050_SCL = 1;
MPU6050_IIC_Delay(DELAY_TIME);
MPU6050_SCL = 0;
MPU6050_SDA = 1;
MPU6050_IIC_Delay(DELAY_TIME);
}
/****
*******等待应答信号
*****/
bit MPU6050_IIC_WaitAck(void)
{
bit ackbit;
MPU6050_SDA = 1;
MPU6050_SCL = 1;
MPU6050_IIC_Delay(DELAY_TIME);
ackbit = MPU6050_SDA;
MPU6050_SCL = 0;
MPU6050_IIC_Delay(DELAY_TIME);
return ackbit;
}
发送一个字节:SCL低电平期间,主机将数据位依次放到SDA线上(高位在前),然后拉高SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可发送一个字节。
代码如下:
/****
*******I2C总线发送一个字节数据
*****/
void MPU6050_IIC_SendByte(uchar byte)
{
uchar i;
MPU6050_SCL = 0;
for(i=0; i<8; i++)
{
if(byte & 0x80)
MPU6050_SDA = 1;
else
MPU6050_SDA = 0;
MPU6050_IIC_Delay(DELAY_TIME);
MPU6050_SCL = 1;
MPU6050_IIC_Delay(DELAY_TIME);
MPU6050_SCL = 0;
MPU6050_IIC_Delay(DELAY_TIME);
byte <<= 1;
}
MPU6050_IIC_WaitAck();
}
接收一个字节:SCL低电平期间,从机将数据位依次放到SDA总线上(高位在前),然后拉高SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节(主机在接收之前,需要释放SDA)
代码如下:
/****
*******I2C总线接收一个字节数据
*****/
uchar MPU6050_IIC_RecByte(bit ackbit)
{
uchar i, dat;
MPU6050_SDA = 1;
for(i=0; i<8; i++)
{
MPU6050_SCL = 1;
MPU6050_IIC_Delay(DELAY_TIME);
dat <<= 1;
if(MPU6050_SDA)
dat |= 1;
MPU6050_SCL = 0;
MPU6050_IIC_Delay(DELAY_TIME);
}
MPU6050_IIC_SendAck(ackbit);
return dat;
}
4、MPU6050数据帧
字节写:在“字地址”处写入“数据”
代码如下:
/****
*******向MPU6050的地址address中写入一个字节的数据
*****/
void MPU6050_Write_Data(uchar address,uchar dat)
{
MPU6050_IIC_Start();
MPU6050_IIC_SendByte(MPU6050_SlaveAddress);
MPU6050_IIC_SendByte(address);
MPU6050_IIC_SendByte(dat);
MPU6050_IIC_Stop();
}
随机读:读出在“字地址”处的“数据”
代码如下:
/****
*******从MPU6050的地址address中读取一个字节的数据
*****/
uchar MPU6050_Read_Data(uchar address)
{
uchar dat;
MPU6050_IIC_Start();
MPU6050_IIC_SendByte(MPU6050_SlaveAddress);
MPU6050_IIC_SendByte(address);
MPU6050_IIC_Start();
MPU6050_IIC_SendByte(MPU6050_SlaveAddress + 1);
dat = MPU6050_IIC_RecByte(MPU6050_ACK);
MPU6050_IIC_Stop();
return(dat);
}
六、流程设计
首先初始化引脚,然后发送起始位,再发送从机设备地址写,接下来发送命令地址,重新发送一次起始位,再发送从机设备地址读,然后先读取高字节数据,再读取低字节数据,将读取的高字节数据和低字节数据整合为一个数据进行返回。