STM32读取MPU6050数据以及使用MPU6050辅助IIC读取LIS3MDLTR

一、概述

        MPU6050是一款集成了加速度计和陀螺仪的传感器,LIS3MDLTR是一款磁力计传感器。下面将介绍如何在STM32平台上读取MPU6050的数据,并通过MPU6050的辅助IIC接口读取LIS3MDLTR的数据。

二、硬件连接

        主控芯片使用STM32C8T6,通过IIC读取MPU6050的陀螺仪和加速度的数据,使用MPU6050的辅助IIC读取LIS3MDLTR磁力计数据。STM32的PB10、PB11引脚分别连接MPU6050的SCL和SDA引脚,MPU6050的AUX_CL和AUX_DA引脚连接LIS3MDLTR的SCL和SDA引脚,如图所示的产品数据手册接口示意图。

二、软件实现

2.1 IIC通信

        参考正点原子的IIC通信程序,IIC多字节的读函数与写函数分别如下:

uint8_t MPU_Multi_Read(uint8_t addr,uint8_t reg,uint8_t len,uint8_t *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;	
}
uint8_t MPU_Multi_Write(uint8_t addr,uint8_t reg,uint8_t len,uint8_t *buf)
{
  uint8_t 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;	
} 

两个函数中的变量addr和reg分别是器件地址和器件寄存器地址。本文中MPU6050的AD0接地,其地址为0x68,LIS3MDLTR的SD0接3.3V,其地址为0x1E。

2.2 MPU6050和LIS3MDLTR相关配置

1. MPU6050配置

        (1)设置陀螺仪量程±2000dps。根据数据手册的器件寄存器介绍,即寄存器(MPU_GYRO_CFG)地址是0x1B。

 FS_SEL根据下表选择陀螺仪输出的范围,选择量程范围是±2000dps(MPU6050_Gyr_2000)。

MPU_Write_Byte(MPU_ADDR, MPU_GYRO_CFG, MPU6050_Gyr_2000);

        (2)设置加速度计量程±16g,寄存器(MPU_ACC_CFG)地址是0x1C,量程范围选择±16g( MPU6050_Acc_16)。

MPU_Write_Byte(MPU_ADDR, MPU_ACC_CFG, MPU6050_Acc_16);

         (3)设置采样率500Hz,相关寄存器描述如下:

2. LIS3MDLTR配置

        由于使用MPU6050的辅助IIC来读取 LIS3MDLTR数据,因此首先需要对MPU6050的相关寄存器配置,具体描述如图所示。

        根据数据手册相关描述,本次设置首先对MPU6050设置旁通状态,由STM32直接驱动LIS3MDLTR,配置LIS3MDLTR相关寄存器,为读取数据做准备。然后对MPU6050设置主机模式,由LIS3MDLTR的数据通过辅助IIC传输至序号为73到96的寄存器,最后STM32通过MPU6050的IIC一起读出陀螺仪,加速度计和磁力计数据,完成数据的读取。

        需要注意的是:对LIS3MDLTR的数据读取首先通过配置MPU6050的INT_PIN_CFG寄存器。INT_PIN_CFG寄存器的位1,当I2C_BYPASS_EN等于1且I2C_MST_EN(寄存器106位5)等于0时,主机应用程序处理器将能够直接访问MPU-60X0的辅助IIC总线。当该位等于0时,无论I2C_MST_EN的状态如何,主机应用程序处理器都将无法直接访问MPU-60X0的辅助IIC总线。

以下是使用辅助IIC读取LIS3MDLTR的步骤:

(1)设置MPU6050为直通模式,以便主控配置LIS3MDLTR。

(2)配置LIS3MDLTR。

(3)读取LIS3MDLTR数据。

(4)设置MPU6050为主模式,STM32读取数据。

MPU_Write_Byte(MPU_ADDR,MPU_INTBP_CFG, 0x02); //设置旁通状态
MPU_Write_Byte(MPU_ADDR,MPU_USER_CTRL, 0x00); //辅助 I2C 总线由主I2C总线(SDA 和 SCL)驱动。
MPU_Write_Byte(LIS3MDL_ADRESS, LIS3MDL_CTRL_REG1, FAST_ODR_300_HP);  //配置CTRL_REG1寄存器
MPU_Write_Byte(LIS3MDL_ADRESS, LIS3MDL_CTRL_REG2, FULL_SCALE_8);     //配置CTRL_REG2寄存器
MPU_Write_Byte(LIS3MDL_ADRESS, LIS3MDL_CTRL_REG3, CCM);              //配置CTRL_REG3寄存器            
MPU_Write_Byte(LIS3MDL_ADRESS, LIS3MDL_CTRL_REG4, (Z_HPM | BLE_MSB));//配置CTRL_REG4寄存器

MPU_Write_Byte(MPU_ADDR,MPU_INTBP_CFG, 0x00);                        //设置主模式。
MPU_Write_Byte(MPU_ADDR,MPU_USER_CTRL, 0x22); 
MPU_Write_Byte(MPU_ADDR,MPU_I2CMST_CTRL, 0x0D);
MPU_Write_Byte(MPU_ADDR,MPU_I2CSLV0_ADDR, (LIS3MDL_ADRESS|0x80));
MPU_Write_Byte(MPU_ADDR,MPU_I2CSLV0, LIS3MDL_OUT_X_L);
MPU_Write_Byte(MPU_ADDR,MPU_I2CSLV0_CTRL,EXT_SENS_DATA_00);

        LIS3MDLTR的四个配置寄存器是设置磁力计的量程范围和输出速率等相关配置,与MPU6050的配置类似,这里不再叙述。LIS3MDLTR和MPU6050还有一些其他配置,可以根据两个芯片的数据手册按需设置。

2.3 程序设计

1. 配置初始化

uint8_t MPU_Init(void)
{ 
  uint8_t res; 
  MPU_IIC_Init();//初始化IIC总线
  MPU_Write_Byte(MPU_ADDR,MPU_PWR_MGMT1 ,0X80);	        //复位MPU6050
  delay_ms(100);
  MPU_Write_Byte(MPU_ADDR,MPU_PWR_MGMT1 ,0X00);	        //唤醒MPU6050 
	
  MPU_Write_Byte(MPU_ADDR,MPU_INTBP_CFG, 0x02);         //设置旁通状态
  MPU_Write_Byte(MPU_ADDR,MPU_USER_CTRL, 0x00);         //辅助 IIC 总线由主IIC总线驱动。
  res=MPU_Read_Byte(LIS3MDL_ADRESS, LIS3MDL_ID); 
  if(res==LIS3MDL_ID_DATA)                              //器件ID正确
  {
	MPU_Write_Byte(LIS3MDL_ADRESS, LIS3MDL_CTRL_REG1, FAST_ODR_300_HP);
	MPU_Write_Byte(LIS3MDL_ADRESS, LIS3MDL_CTRL_REG2, FULL_SCALE_8);
	MPU_Write_Byte(LIS3MDL_ADRESS, LIS3MDL_CTRL_REG3, CCM);
	MPU_Write_Byte(LIS3MDL_ADRESS, LIS3MDL_CTRL_REG4, (Z_HPM | BLE_MSB));
  }else return 1;
  MPU_Write_Byte(MPU_ADDR,MPU_INTBP_CFG, 0x00);         //设置主模式。
  MPU_Write_Byte(MPU_ADDR,MPU_USER_CTRL, 0x22); 
  MPU_Write_Byte(MPU_ADDR,MPU_I2CMST_CTRL, 0x0D);
  MPU_Write_Byte(MPU_ADDR,MPU_I2CSLV0_ADDR, (LIS3MDL_ADRESS|0x80));
  MPU_Write_Byte(MPU_ADDR,MPU_I2CSLV0, LIS3MDL_OUT_X_L);
  MPU_Write_Byte(MPU_ADDR,MPU_I2CSLV0_CTRL, I2C_SLV0_CFG);
  MPU_Write_Byte(MPU_ADDR, MPU_GYRO_CFG, MPU6050_Gyr_2000);//陀螺仪传感器,±2000dps
  MPU_Write_Byte(MPU_ADDR, MPU_ACC_CFG, MPU6050_Acc_16);//加速度传感器,±16g
  MPU_Write_Byte(MPU_ADDR,MPU_INT_EN ,0X00);	        //关闭所有中断
  MPU_Write_Byte(MPU_ADDR,MPU_FIFO_EN ,0X00);	        //关闭FIFO
  res=MPU_Read_Byte(MPU_ADDR,MPU_DEVICE_ID); 
  if(res==MPU_ADDR)//器件ID正确
  {
	MPU_Write_Byte(MPU_ADDR,MPU_PWR_MGMT1 ,0X01);	    //设置CLKSEL,PLL X轴为参考
	MPU_Write_Byte(MPU_ADDR,MPU_PWR_MGMT2 ,0X00);	    //加速度与陀螺仪都工作
	MPU_Set_Rate(500);						            //设置采样率为500Hz
  }
  else return 1;
  return 0;
}

2. 读取数据

uint8_t MPU_Raw_Data(MPU6050_Raw_Data *Raw_Data)
{
	uint8_t buf[14],res,buf1[6];
	res=MPU_Multi_Read(MPU_ADDR,MPU_ACCEL_XOUTH,14,buf);
	if(res==0)
	{
		Raw_Data->Acc_x_Raw=((uint16_t)buf[0]<<8)|buf[1];
		Raw_Data->Acc_y_Raw=((uint16_t)buf[2]<<8)|buf[3];
		Raw_Data->Acc_z_Raw=((uint16_t)buf[4]<<8)|buf[5];
		Raw_Data->Temp_Raw=((uint16_t)buf[6]<<8)|buf[7];
		Raw_Data->Gyr_x_Raw=((uint16_t)buf[8]<<8)|buf[9];
		Raw_Data->Gyr_y_Raw=((uint16_t)buf[10]<<8)|buf[11];
		Raw_Data->Gyr_z_Raw=((uint16_t)buf[12]<<8)|buf[13];
	}
	res=MPU_Multi_Read(MPU_ADDR,EXT_SENS_DATA_00,6,buf1);
	if(res==0)
	{
		Raw_Data->Guass_x_Raw=((uint16_t)buf1[0]<<8)|buf1[1];
		Raw_Data->Guass_y_Raw=((uint16_t)buf1[2]<<8)|buf1[3];
		Raw_Data->Guass_z_Raw=((uint16_t)buf1[4]<<8)|buf1[5];
	}
	return res;
}

三、数据输出

        采集的数据通过串口输出显示,从数据特征来看应该是正确采集到了陀螺仪、加速度计和磁力计数据。有错误的地方,欢迎指正,相互交流。

四、参考资料

MPU6050辅助IIC(HMC5883L,STM32F103C8T6)_mpu6050与hmc5883-CSDN博客http://www.openedv.com/docs/modules/other/ATK-MPU6050.html

作者:洛洛xin

物联沃分享整理
物联沃-IOTWORD物联网 » STM32读取MPU6050数据以及使用MPU6050辅助IIC读取LIS3MDLTR

发表回复