MPU6050

一.简介

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值