本文为个人学习笔记,不喜勿喷。
学习目标:在熟知I2C通信协议的基础上,以MPU6050为例子,学习使用I2C通信协议实现获取外部设备的信息。
主要内容即通过I2C的读、写获取MPU6050寄存器的各个参数。
通过下图的时序,先进行写操作,写操作时,从机是得知道指定寄存器的,而读寄存器却不需要,利用这个特点,先假装要写,骗从机指向要写入的寄存器,寄存器已锁定,下次进行读操作时,会从当前寄存器往下读取。
首先访问MPU6050的地址,再访问MPU6050的寄存器地址,这样指针就指向该地址,下次执行读寄存器操作时,可以直接读该寄存器的值。相当于你可以指定到哪个寄存器里写数据,但当你读数据时,你发送第一个地址时,从机知道了你想要读数据,便会从指针指定的寄存器读给你。
写入寄存器的代码
相当于为读操作铺路
void MPU6050_WriteReg(uint8_t RegAddress,uint8_t Data )
{
MyIC2_Start();
MyIC2_SendByte(MPU6050_Address);
MyIC2_ReceiveAck();
MyIC2_SendByte(RegAddress);
MyIC2_ReceiveAck();
MyIC2_SendByte(Data);
MyIC2_ReceiveAck();
MyIC2_Stop();
}
读寄存器的代码
uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{
uint8_t Data;
MyIC2_Start();
MyIC2_SendByte(MPU6050_Address);
MyIC2_ReceiveAck();
MyIC2_SendByte(RegAddress);
MyIC2_ReceiveAck();
//重复起始
MyIC2_Start();
//读指令
MyIC2_SendByte(MPU6050_Address | 0X01);
MyIC2_ReceiveAck();
Data=MyIC2_ReceiveByte();
//练习:读多个字节
MyIC2_SendAck(1);
MyIC2_Stop();
return Data;
}
MPU6050的寄存器配置
自己翻文档,巴拉巴拉
void MPU6050_Init(void)
{
MyIC2_Init();
//电源管理寄存器1
MPU6050_WriteReg(MPU6050_PWR_MGMT_1,0X01);
//电源管理寄存器2
MPU6050_WriteReg(MPU6050_PWR_MGMT_2,0X00);
//采样率分频寄存器
MPU6050_WriteReg(MPU6050_SMPLRT_DIV,0X09);
//配置寄存器
MPU6050_WriteReg(MPU6050_CONFIG,0X06);
//陀螺仪配置寄存器
MPU6050_WriteReg(MPU6050_GYRO_CONFIG,0x18);
//加速度计配置寄存器
MPU6050_WriteReg(MPU6050_ACCEL_CONFIG,0X18);
}
//主要知识,C语言一次只能返回一个值,使用指针能返回多个值
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ,
int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ)
{
uint8_t DataH,DataL;
//加速度寄存器X轴的高八位
DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);
//加速度寄存器X的低八位
DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);
*AccX = (DataH << 8) | DataL;
//加速度寄存器Y轴的高八位
DataH=MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);
//加速度寄存器Y的低八位
DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);
*AccY = (DataH << 8) | DataL;
//加速度寄存器Z轴的高八位
DataH=MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);
//加速度寄存器Z的低八位
DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);
*AccZ = (DataH << 8) | DataL;
//陀螺仪寄存器X轴的高八位
DataH=MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);
//陀螺仪寄存器X的低八位
DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);
*GyroX = (DataH << 8) | DataL;
//陀螺仪寄存器Y轴的高八位
DataH=MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);
//陀螺仪寄存器Y的低八位
DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);
*GyroY = (DataH << 8) | DataL;
//陀螺仪寄存器Z轴的高八位
DataH=MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);
//陀螺仪寄存器Z的低八位
DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);
*GyroZ = (DataH << 8) | DataL;
}
另外一个写法:
void MPU6050_ReadRegs(uint8_t RegAddress,uint8_t *pData,uint16_t Size)
{
MyIC2_Start();
MyIC2_SendByte(MPU6050_Address);
MyIC2_ReceiveAck();
MyIC2_SendByte(RegAddress);
MyIC2_ReceiveAck();
MyIC2_Start();
MyIC2_SendByte(MPU6050_Address | 0x01);
MyIC2_ReceiveAck();
while(Size--)
{
*pData++ = MyIC2_ReceiveByte();
if(Size != 0)
{
MyIC2_SendAck(0);
}
else{
MyIC2_SendAck(1);
}
}
MyIC2_Stop();
}
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ,
int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ)
{
uint8_t buf[14];
MPU6050_ReadRegs(MPU6050_ACCEL_XOUT_H,buf,14);
*AccX = (buf[0] << 8) + buf[1];
*AccY = (buf[2] << 8) + buf[3];
*AccZ = (buf[4] << 8) + buf[5];
*GyroX = (buf[6] << 8) + buf[7];
*GyroY = (buf[8] << 8) + buf[9];
*GyroZ = (buf[10] << 8) + buf[11];
}