MUP6050简介
首先mpu6050是由三个陀螺仪和三个加速度传感器组成的6轴运动处理组件(如下图所示)。mpu6050还含有两个IIC接口,一个可作为主接口给单片机传输数据,另一个可以接入外部磁力传感器。
mpu6050的输出形式为数字形式输出6轴或9轴1的旋转矩阵,四元数,欧拉角公式的融合演算数据(需要DMP2支持)
MPU6050与单片机接线
端口 | 连接 |
---|---|
VCC | 接3.3V或5V电源 |
GND | 接地 |
SCL | 作为从机,接单片机的I2C2_SCL |
SDA | 作为从机,接单片机的I2C2_SDA |
XDA | 辅助IIC用来连接其他器件,不需要连接单片机 |
XCL | 辅助IIC用来连接其他器件,不需要连接单片机 |
AD0 | 地址管脚(可以不接单片机) |
INT | 中断引脚(可以不接单片机) |
MPU6050作为一个IIC从机设备的时候,有8位地址,高7位的地址是固定的,就是WHOAMI寄存器的默认——0x68,最低的一位是由AD0的连线决定的.
AD0接GND时候,高8位的最后一位是0 所以整个iic从几地址就是0x68;
AD0接VCC时候,高8位的最后一位是1 所以整个iic从几地址就是0x69.
四、程序里需要知道的
MPU6050的代码实现(以keil5软件为例)
MPU6050 IIC配置
- 初始化IIC接口(初始化与mpu6050连接的SDA与SCL数据线)
void MPU_IIC_Init(void)
{ GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//先使能外设IO PORTB时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11; // 端口配置,这里以我连接的SDA与SCL为例GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHzGPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIO GPIO_SetBits(GPIOB,GPIO_Pin_10|GPIO_Pin_11); //PB10,PB11 输出高,都置高可以使模块处于待机模式}
- IIC开始信号(SCL为高电平,SDA由高向低跳变开始传输数据)
void MPU_IIC_Start(void)
{MPU_SDA_OUT(); //sda线输出MPU_IIC_SDA=1; MPU_IIC_SCL=1;MPU_IIC_Delay();MPU_IIC_SDA=0;//START:when CLK is high,DATA change form high to low MPU_IIC_Delay();MPU_IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}
- IIC开始信号(SCL为高电平,SDA由低向高跳变开始传输数据)
void MPU_IIC_Stop(void)
{MPU_SDA_OUT();//sda线输出MPU_IIC_SCL=0;MPU_IIC_SDA=0;//STOP:when CLK is high DATA change form low to highMPU_IIC_Delay();MPU_IIC_SCL=1; MPU_IIC_SDA=1;//发送I2C总线结束信号MPU_IIC_Delay();
}
- 等待信号接收
u8 MPU_IIC_Wait_Ack(void)//返回值为1接收失败;返回值为0接收成功
{u8 ucErrTime=0;MPU_SDA_IN(); //SDA设置为输入 MPU_IIC_SDA=1;MPU_IIC_Delay(); MPU_IIC_SCL=1;MPU_IIC_Delay(); while(MPU_READ_SDA){ucErrTime++;if(ucErrTime>250){MPU_IIC_Stop();return 1;}}MPU_IIC_SCL=0;//时钟输出0 return 0;
}
- 产生ACK应答
void MPU_IIC_Ack(void)
{MPU_IIC_SCL=0;MPU_SDA_OUT();MPU_IIC_SDA=0;MPU_IIC_Delay();MPU_IIC_SCL=1;MPU_IIC_Delay();MPU_IIC_SCL=0;
}
- 产生ACK应答
void MPU_IIC_NAck(void)
{MPU_IIC_SCL=0;MPU_SDA_OUT();MPU_IIC_SDA=1;MPU_IIC_Delay();MPU_IIC_SCL=1;MPU_IIC_Delay();MPU_IIC_SCL=0;
}
MPU6050初始化
代码来自b站大佬“晴时箫声”
u8 MPU_Init(void)
{ u8 res;GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//使能AFIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//先使能外设IO PORTA时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; // 端口配置GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHzGPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOAGPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//禁止JTAG,从而PA15可以做普通IO使用,否则PA15不能做普通IO!!!MPU_AD0_CTRL=0; //控制MPU6050的AD0脚为低电平,从机地址为:0X68MPU_IIC_Init();//初始化IIC总线MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X80); //复位MPU6050delay_ms(100);MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X00); //唤醒MPU6050 MPU_Set_Gyro_Fsr(3); //陀螺仪传感器,±2000dpsMPU_Set_Accel_Fsr(0); //加速度传感器,±2gMPU_Set_Rate(50); //设置采样率50HzMPU_Write_Byte(MPU_INT_EN_REG,0X00); //关闭所有中断MPU_Write_Byte(MPU_USER_CTRL_REG,0X00); //I2C主模式关闭MPU_Write_Byte(MPU_FIFO_EN_REG,0X00); //关闭FIFOMPU_Write_Byte(MPU_INTBP_CFG_REG,0X80); //INT引脚低电平有效res=MPU_Read_Byte(MPU_DEVICE_ID_REG);if(res==MPU_ADDR)//器件ID正确{MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X01); //设置CLKSEL,PLL X轴为参考MPU_Write_Byte(MPU_PWR_MGMT2_REG,0X00); //加速度与陀螺仪都工作MPU_Set_Rate(50); //设置采样率为50Hz}else return 1;return 0;
}
所调用的函数
u8 MPU_Set_Gyro_Fsr(u8 fsr)
{return MPU_Write_Byte(MPU_GYRO_CFG_REG,fsr<<3);//设置陀螺仪满量程范围
}
u8 MPU_Set_Accel_Fsr(u8 fsr)
{return MPU_Write_Byte(MPU_ACCEL_CFG_REG,fsr<<3);//设置加速度传感器满量程范围
}
8 MPU_Set_LPF(u16 lpf)
{u8 data=0;if(lpf>=188)data=1;else if(lpf>=98)data=2;else if(lpf>=42)data=3;else if(lpf>=20)data=4;else if(lpf>=10)data=5;else data=6; return MPU_Write_Byte(MPU_CFG_REG,data);//设置数字低通滤波器
}
u8 MPU_Set_Rate(u16 rate)
{u8 data;if(rate>1000)rate=1000;if(rate<4)rate=4;data=1000/rate-1;data=MPU_Write_Byte(MPU_SAMPLE_RATE_REG,data); //设置数字低通滤波器return MPU_Set_LPF(rate/2); //自动设置LPF为采样率的一半
}
short MPU_Get_Temperature(void)
{u8 buf[2]; short raw;float temp;MPU_Read_Len(MPU_ADDR,MPU_TEMP_OUTH_REG,2,buf); raw=((u16)buf[0]<<8)|buf[1]; temp=36.53+((double)raw)/340; return temp*100;;
}
u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz)
{u8 buf[6],res; res=MPU_Read_Len(MPU_ADDR,MPU_GYRO_XOUTH_REG,6,buf);if(res==0){*gx=((u16)buf[0]<<8)|buf[1]; *gy=((u16)buf[2]<<8)|buf[3]; *gz=((u16)buf[4]<<8)|buf[5];} return res;;
}
u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az)
{u8 buf[6],res; res=MPU_Read_Len(MPU_ADDR,MPU_ACCEL_XOUTH_REG,6,buf);if(res==0){*ax=((u16)buf[0]<<8)|buf[1]; *ay=((u16)buf[2]<<8)|buf[3]; *az=((u16)buf[4]<<8)|buf[5];} return res;;
}
u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf)
{u8 i; MPU_IIC_Start(); MPU_IIC_Send_Byte((addr<<1)|0);//发送器件地址+写命令 if(MPU_IIC_Wait_Ack()) //等待应答{MPU_IIC_Stop(); return 1; }MPU_IIC_Send_Byte(reg); //写寄存器地址MPU_IIC_Wait_Ack(); //等待应答for(i=0;i<len;i++){MPU_IIC_Send_Byte(buf[i]); //发送数据if(MPU_IIC_Wait_Ack()) //等待ACK{MPU_IIC_Stop(); return 1; } } MPU_IIC_Stop(); return 0;
}
u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf)
{ MPU_IIC_Start(); MPU_IIC_Send_Byte((addr<<1)|0);//发送器件地址+写命令 if(MPU_IIC_Wait_Ack()) //等待应答{MPU_IIC_Stop(); return 1; }MPU_IIC_Send_Byte(reg); //写寄存器地址MPU_IIC_Wait_Ack(); //等待应答MPU_IIC_Start();MPU_IIC_Send_Byte((addr<<1)|1);//发送器件地址+读命令 MPU_IIC_Wait_Ack(); //等待应答 while(len){if(len==1)*buf=MPU_IIC_Read_Byte(0);//读数据,发送nACK else *buf=MPU_IIC_Read_Byte(1); //读数据,发送ACK len--;buf++; } MPU_IIC_Stop(); //产生一个停止条件 return 0;
}
u8 MPU_Write_Byte(u8 reg,u8 data)
{ MPU_IIC_Start(); MPU_IIC_Send_Byte((MPU_ADDR<<1)|0);//发送器件地址+写命令 if(MPU_IIC_Wait_Ack()) //等待应答{MPU_IIC_Stop(); return 1; }MPU_IIC_Send_Byte(reg); //写寄存器地址MPU_IIC_Wait_Ack(); //等待应答 MPU_IIC_Send_Byte(data);//发送数据if(MPU_IIC_Wait_Ack()) //等待ACK{MPU_IIC_Stop(); return 1; } MPU_IIC_Stop(); return 0;
}
u8 MPU_Read_Byte(u8 reg)
{u8 res;MPU_IIC_Start(); MPU_IIC_Send_Byte((MPU_ADDR<<1)|0);//发送器件地址+写命令 MPU_IIC_Wait_Ack(); //等待应答 MPU_IIC_Send_Byte(reg); //写寄存器地址MPU_IIC_Wait_Ack(); //等待应答MPU_IIC_Start();MPU_IIC_Send_Byte((MPU_ADDR<<1)|1);//发送器件地址+读命令 MPU_IIC_Wait_Ack(); //等待应答 res=MPU_IIC_Read_Byte(0);//读取数据,发送nACK MPU_IIC_Stop(); //产生一个停止条件 return res;
}
以上代码就可以使mpu6050正常工作了。
输出9轴需要外接磁传感器 ↩︎
官方自带的数字运动处理器 ↩︎