一.简介
MPU6050是一个6轴姿态传感器,可以测量芯片自身X、Y、Z轴的加速度、角速度参数,通过数据融合,可进一步得到姿态角,常应用于平衡车、飞行器等需要检测自身姿态的场景
3轴加速度计(Accelerometer):测量X、Y、Z轴的加速度
3轴陀螺仪传感器(Gyroscope):测量X、Y、Z轴的角速度
16位ADC采集传感器的模拟信号,量化范围:-32768~32767
加速度计满量程选择:±2、±4、±8、±16(g)
陀螺仪满量程选择: ±250、±500、±1000、±2000(°/sec)
可配置的数字低通滤波器
可配置的时钟源
可配置的采样分频 I2C从机地址:1101000(AD0=0) 1101001(AD0=1)
地址是七位,发送数据是8位,所以一种方式是读写110 1000(0x68)或者是带上最后一位读写位直接左移一位1101 0000(0xD0)
二.硬件电路
XCL和XDA一般就是用来外接磁力计或者是气压计,用到MPU6050的解算功能。
三.编写软件IIC代码
#include "stm32f10x.h" // Device header
#include "Delay.h"
#define MyIIC_W_SCL(x) do{x?GPIO_SetBits(GPIOB,GPIO_Pin_10):GPIO_ResetBits(GPIOB,GPIO_Pin_10);}while(0)
#define MyIIC_W_SDA(x) do{x?GPIO_SetBits(GPIOB,GPIO_Pin_11):GPIO_ResetBits(GPIOB,GPIO_Pin_11);}while(0)
void MyIIC_W_SCL(uint8_t BitValue)
{
GPIO_WriteBit(GPIOB,GPIO_Pin_10,(BitAction)BitValue);
Delay_ms(10);
}
void MyIIC_W_SDA(uint8_t BitValue)
{
GPIO_WriteBit(GPIOB,GPIO_Pin_11,(BitAction)BitValue);
Delay_ms(10);
}
uint8_t My_IIC_R_SDA()
{
uint8_t BitValue;
BitValue=GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11);//读取输入的电平
Delay_ms(10);
return BitValue;
}
void MyIIC_Init()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
//设备的SCL和SDA均要配置成开漏输出模式,开漏输出不代表只能输出还可以输入
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11|GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_10);//两个引脚电平都设置成高电平
GPIO_SetBits(GPIOB,GPIO_Pin_11);
}
void MyIIC_Start()
{
MyIIC_W_SDA(1);
MyIIC_W_SCL(1);
MyIIC_W_SDA(0);
MyIIC_W_SCL(0);
}
void MyIIC_Stop()
{
MyIIC_W_SDA(0);
MyIIC_W_SCL(1);
MyIIC_W_SDA(1);
}
void MyIIC_SendByte(uint8_t Byte)
{
for(uint8_t i=0;i<8;i++)
{
MyIIC_W_SDA(Byte&(0x80>>i));//将Byte值转化成SDA的电平信号
MyIIC_W_SCL(1);
MyIIC_W_SCL(0);
}
}
uint8_t MyIIC_ReceiveByte()
{
uint8_t Byte=0x00;
MyIIC_W_SDA(1);//释放SDA
for(uint8_t i=0;i<8;i++)
{
MyIIC_W_SCL(1);
if(My_IIC_R_SDA()==1)Byte|=(0x80>>i);
MyIIC_W_SCL(0);
}
return Byte;
}
void MyIIC_SendAck(uint8_t AckBit)
{
MyIIC_W_SDA(AckBit);
MyIIC_W_SCL(1);
MyIIC_W_SCL(0);
}
uint8_t MyIIC_ReceiveAck()
{
uint8_t AckBit=0;
MyIIC_W_SDA(1);//释放SDA
MyIIC_W_SCL(1);
if(My_IIC_R_SDA()==1)AckBit=1;
MyIIC_W_SCL(0);
return AckBit;
}
测试应答信号
int main(void)
{
OLED_Init();
MyIIC_Init();
MyIIC_Start();
//后面紧跟的是写入设备地址
MyIIC_SendByte(0xD0);//发送1101 000 0最后一个0代表即将进行写入
uint8_t ACK=MyIIC_ReceiveAck();//接收应答位
MyIIC_Stop();
while (1)
{
OLED_ShowNum(1,1,ACK,3);
}
}
接收应答0,代表接收应答
四.编写MPU6050控制代码
测试模块
int main(void)
{
OLED_Init();
MPU6050_Init();
//验证读寄存器
uint8_t ID=MPU6050_ReadReg(0x75);
OLED_ShowHexNum(1,1,ID,4);//0x75的默认值是0x68
//验证写寄存器
MPU6050_WriteReg(0x6B,0x00);//给0x6B寄存器写入0x00解除睡眠模式
MPU6050_WriteReg(0x19,0xAA);//给0x19采样率寄存器写0xAA
uint8_t reg=MPU6050_ReadReg(0x19);
OLED_ShowHexNum(2,1,reg,4);
while (1)
{
}
}
#define MPU6050_ADDRESS 0xD0
void MPU6050_WriteReg(uint8_t RegAddress,uint8_t Data)//指定地址写寄存器
{
MyIIC_Start();
MyIIC_SendByte(MPU6050_ADDRESS);
MyIIC_ReceiveAck();
MyIIC_SendByte(RegAddress);
MyIIC_ReceiveAck();//接收应答位这里就不判断了
MyIIC_SendByte(Data);
MyIIC_ReceiveAck();//接收应答位这里就不判断了
MyIIC_Stop();
}
void MPU6050_WriteRegArray(uint8_t RegAddress,uint8_t Arr[3])//指定地址写
{
MyIIC_Start();
MyIIC_SendByte(MPU6050_ADDRESS);
MyIIC_ReceiveAck();
MyIIC_SendByte(RegAddress);
MyIIC_ReceiveAck();//接收应答位这里就不判断了
for(uint8_t i=0;i<2;i++)
{
MyIIC_SendByte(Arr[i]);
MyIIC_ReceiveAck();//接收应答位这里就不判断了
}
MyIIC_Stop();
}
uint8_t MPU6050_ReadReg(uint8_t RegAddress)//指定地址写
{
uint8_t Data;
MyIIC_Start();
MyIIC_SendByte(MPU6050_ADDRESS);
MyIIC_ReceiveAck();
MyIIC_SendByte(RegAddress);
MyIIC_ReceiveAck();//接收应答位这里就不判断了
//重新读写起始位
MyIIC_Start();
MyIIC_SendByte(MPU6050_ADDRESS|0x01);//最后一位要写1
MyIIC_ReceiveAck();
Data=MyIIC_ReceiveByte();
MyIIC_SendAck(1);
MyIIC_Stop();
return Data;
}
uint8_t* MPU6050_ReadRegArray(uint8_t RegAddress)//指定地址写
{
uint8_t array[3];
MyIIC_Start();
MyIIC_SendByte(MPU6050_ADDRESS);
MyIIC_ReceiveAck();
MyIIC_SendByte(RegAddress);
MyIIC_ReceiveAck();//接收应答位这里就不判断了
//重新读写起始位
MyIIC_Start();
MyIIC_SendByte(MPU6050_ADDRESS|0x01);//最后一位要写1
MyIIC_ReceiveAck();
for(uint8_t i=0;i<2;i++)
{
array[i]=MyIIC_ReceiveByte();
MyIIC_SendAck(0);
}
array[2]=MyIIC_ReceiveByte();
MyIIC_SendAck(1);
MyIIC_Stop();
return array;
}
void MPU6050_Init()
{
MyIIC_Init();
MPU6050_WriteReg(MPU6050_PWR_MGMT_1,0x01);//配置电源管理寄存器1,解除睡眠
MPU6050_WriteReg(MPU6050_PWR_MGMT_2,0x00);//配置电源管理寄存器2
MPU6050_WriteReg(MPU6050_SMPLRT_DIV,0x09);//配置采样分频寄存器
MPU6050_WriteReg(MPU6050_CONFIG,0x06);//配置配置寄存器
MPU6050_WriteReg(MPU6050_GYRO_CONFIG,0x18);//配置陀螺仪配置寄存器
MPU6050_WriteReg(MPU6050_ACCEL_CONFIG,0x18);//配置加速度计配置寄存器
}
void MPU6050_GetData(int16_t*AccX,int16_t*AccY,int*AccZ,
int16_t*GyroX,int16_t*GyroY,int*GyroZ)
{
uint8_t DataH,DataL;
DataH=MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);
DataL=MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);
*AccX=DataH<<8|DataL;
DataH=MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);
DataL=MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);
*AccY=DataH<<8|DataL;
DataH=MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);
DataL=MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);
*AccZ=DataH<<8|DataL;
DataH=MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);
DataL=MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);
*GyroX=DataH<<8|DataL;
DataH=MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);
DataL=MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);
*GyroY=DataH<<8|DataL;
DataH=MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);
DataL=MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);
*GyroZ=DataH<<8|DataL;
}