SPI和IIC协议解析2

博客主要介绍了MPU6050在无人机中的使用,其算法从msp430移植而来。详细阐述了MPU6050基于IIC通信的操作,包括写一个字节、读取、连续写、连续读等,还提及读取加速度、方位、温度及器件设置方法,最后提到了较难的dmp部分。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

接下来就是mpu6050的使用了,是无人机中(最?)重要的模块使用了,而且好像里面的算法还是从msp430里移植过来的。
这个使用的是IIC通信,IIC依然是通用的模拟方式,源文件也一样,先看看mpu6050的源文件怎么写的。

1、首先看看头文件定义了那些函数

u8 MPU_Init(void); 							
u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf);
u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf);
u8 MPU_Write_Byte(u8 reg,u8 data);				
u8 MPU_Read_Byte(u8 reg);						

u8 MPU_Set_Gyro_Fsr(u8 fsr);
u8 MPU_Set_Accel_Fsr(u8 fsr);
u8 MPU_Set_LPF(u16 lpf);
u8 MPU_Set_Rate(u16 rate);
u8 MPU_Set_Fifo(u8 sens);


short MPU_Get_Temperature(void);
u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz);
u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az);

当然寄存器也相当多,可能是功能太强大了吧,先逐个分析函数吧。

2、IIC写一个字节

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

普通的IIC通信,起始信号——发送地址+0——发送寄存器地址——发送数据——终止信号。

3、IIC读取

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);
    MPU_IIC_Stop();			
	return res;		
}

普通的IIC读,起始信号——发送器件地址+0——发寄存器地址——起始信号——器件地址+1——接收数据——终止信号

4、连续写

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())		
		{
			MPU_IIC_Stop();	 
			return 1;		 
		}		
	}    
    MPU_IIC_Stop();	 
	return 0;	
} 

循环写,没啥东西

5、连续读

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);
		else *buf=MPU_IIC_Read_Byte(1);		
		len--;
		buf++; 
	}    
    MPU_IIC_Stop();	
	return 0;	

也是正常的循环读,略了。

6、读取加速度、方位、温度

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

从相应的寄存器里读出来就可以了,好像也挺简单。

7、接下来是对器件的设置,可以通过直接向指定寄存器写值完成,大概是这样的:

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


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

8、最后就是初始化:

u8 MPU_Init(void)
{ 
	u8 res;
  GPIO_InitTypeDef  GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;	
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		
  GPIO_Init(GPIOA, &GPIO_InitStructure);				

	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
	
	MPU_AD0_CTRL=0;		
	
	MPU_IIC_Init();
	MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X80);	
  delay_ms(100);
	MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X00);	
	MPU_Set_Gyro_Fsr(3);					
	MPU_Set_Accel_Fsr(0);				
	MPU_Set_Rate(50);					
	MPU_Write_Byte(MPU_INT_EN_REG,0X00);	
	MPU_Write_Byte(MPU_USER_CTRL_REG,0X00);
	MPU_Write_Byte(MPU_FIFO_EN_REG,0X00);
	MPU_Write_Byte(MPU_INTBP_CFG_REG,0X80);	
	res=MPU_Read_Byte(MPU_DEVICE_ID_REG);
	if(res==MPU_ADDR)
	{
		MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X01);	
		MPU_Write_Byte(MPU_PWR_MGMT2_REG,0X00);	
		MPU_Set_Rate(50);						
 	}else return 1;
	return 0;
}

略了。

8、然后最后的难点就是mpu6050的dmp什么的了,这个是真的长,估计最多只能了解功能,额,先不管了,mpu6050就先过了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值