原理圖待補XXXXXXXXXXXXX。
我們用模拟IIC來控制MPU6050。
首先初始化MPU6050。
關于IIC的code部分大家應該都很熟悉。
這裡給大家看下我們讀取的時序。
/*單位元組寫*/
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())
{
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();
if(MPU_IIC_Wait_Ack())
return 0;
MPU_IIC_Send_Byte(reg);
//MPU_IIC_Wait_Ack();
if(MPU_IIC_Wait_Ack())
return 1;
MPU_IIC_Start();
MPU_IIC_Send_Byte((MPU_ADDR<<1)|1);
//MPU_IIC_Wait_Ack();
if(MPU_IIC_Wait_Ack())
return 2;
res=MPU_IIC_Read_Byte(0);
MPU_IIC_Stop();
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;
}
準備工作做好,接下來是Init MPU6050
u8 MPU_Init(void)
{
u8 res;
MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X80); //複位MPU6050
delay_ms(100);
MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X00); //喚醒MPU6050
MPU_Set_Gyro_Fsr(3); //設定陀螺儀分辨率,±2000dps
MPU_Set_Accel_Fsr(0); //設定加速計分辨率,±2g
MPU_Set_Rate(50); //設定采樣速率
MPU_Write_Byte(MPU_INT_EN_REG,0X00); //關閉所有中斷
MPU_Write_Byte(MPU_USER_CTRL_REG,0X00); //IIC自主模式關閉
MPU_Write_Byte(MPU_FIFO_EN_REG,0X00); //關閉FIFO
MPU_Write_Byte(MPU_INTBP_CFG_REG,0X80); //INT引腳低電平有效
res=MPU_Read_Byte(MPU_DEVICE_ID_REG);
if(res==MPU_ADDR)//檢測讀到的器件ID,注意這裡不是從位址
{
printf(">>> MPU6050 Init Success! <<<\r\n");
MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X01); //設定CLKSEL,PLL,X軸為參考
MPU_Write_Byte(MPU_PWR_MGMT2_REG,0X00); //加速計與陀螺儀都工作
MPU_Set_Rate(50); //再次設定采樣速率
}else
{
printf(">>> MPU6050 Init Failed! <<<\r\n");
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);//ÉèÖüÓËٶȴ«¸ÐÆ÷ÂúÁ¿³Ì·¶Î§
}
/*設定低通濾波*/
u8 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);//ÉèÖÃÊý×ÖµÍͨÂ˲¨Æ÷
}
/*設定采樣速率(假定Fs=1KHz)*/
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;;
}
/*擷取陀螺儀3軸原始值*/
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;;
}
/*擷取加速計3軸原始值*/
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;;
}
設定完成後就可以讀取到陀螺儀的原始值了。
歡迎大家批評指正。可以加QQ:727169295,一起交流學習~~~