STM32与MS5837压力传感器的I2C通讯

MS5837压力传感器是一种可用于电路板上,适用于检测10-1200mbar压力范围的传感器,灵敏度非常高,理论上能够检测到0.01mbar的压力变化,实际使用过程中测试并无明显的变化。

MS5837采用I2C总线通讯,与STM32的MCU可以实现I2C通讯。硬件连接方式如下:

STM32与MS5837压力传感器的I2C通讯_第1张图片

MS5837只有5个基本命令:复位、读取出厂校准值、数据1转换(压力值数据)、数据2转换(温度值数据)和读取ADC的转换结果。具体分配如下:

STM32与MS5837压力传感器的I2C通讯_第2张图片

因为MS5837的地址是固定的,所以一个I2C总线只能挂1个MS5837模块。为了让程序具有较好的可移植性,我们在便写程序时不使用对硬件的直接操作,而采用函数指针来操作,所以我们定义了:

/*向MS5837下发指令,指令格式均为1个字节*/

typedef void (*WriteCommandToMs5837Type)(uint8_t deviceAddress,uint8_t command);

/*从MS5837读取多个字节数据的值*/

typedef void (*ReadBytesFromMs5837Type)(uint8_t deviceAddress,uint8_t *pData,uint16_t bytesNum);

以上两个函数指针来实现针对硬件的读写操作。接下来我们开始编写代码。

1)复位操作

复位操作的数据流如下图所示,只需要发送一条命令就可完成:

STM32与MS5837压力传感器的I2C通讯_第3张图片

/*复位MS5837操作*/
void ResetForMs5837(uint8_t deviceAddress,WriteCommandToMs5837Type WriteCommandToMs5837)
{
  uint8_t command=COMMAND_RESET;
  /*下发复位命令*/
  WriteCommandToMs5837(deviceAddress,command);
}

2)读取校准值

校准值是出厂时厂家校准的各种系数,每台设备都有差异,是固定不变的,只需要一次读取就可以了,共有6个系数,均为16为整数。首先发送读系数的命令,然后读取就可以了,每次读取1个,分6次读取。过程数据流如下图所示:

STM32与MS5837压力传感器的I2C通讯_第4张图片

/*从MS5837的PROM中读取校准数据*/
void GetCalibrationData(uint8_t deviceAddress,uint16_t *caliPara,WriteCommandToMs5837Type WriteCommandToMs5837,ReadBytesFromMs5837Type ReadBytesFromMs5837)
{
  /*C1压力灵敏度*/
 caliPara[0]=ReadPromFromMs5837(deviceAddress,COMMAND_PROM_READ_C1,WriteCommandToMs5837,ReadBytesFromMs5837);

  /*C2压力补偿值*/
 caliPara[1]=ReadPromFromMs5837(deviceAddress,COMMAND_PROM_READ_C2,WriteCommandToMs5837,ReadBytesFromMs5837);

  /*C3压力灵敏度温度系数*/
 caliPara[2]=ReadPromFromMs5837(deviceAddress,COMMAND_PROM_READ_C3,WriteCommandToMs5837,ReadBytesFromMs5837);

  /*C4压力补偿温度系数*/
 caliPara[3]=ReadPromFromMs5837(deviceAddress,COMMAND_PROM_READ_C4,WriteCommandToMs5837,ReadBytesFromMs5837);

  /*C5参考温度*/
 caliPara[4]=ReadPromFromMs5837(deviceAddress,COMMAND_PROM_READ_C5,WriteCommandToMs5837,ReadBytesFromMs5837);

  /*C6温度传感器温度系数*/  caliPara[5]=ReadPromFromMs5837(deviceAddress,COMMAND_PROM_READ_C6,WriteCommandToMs5837,ReadBytesFromMs5837);

}

3)读取转换值

读取转换结果值是我们的目的,可以读取温度和压力两个量,不过一次只能读一个。首先发送命令设定采集压力还是温度,并设定精度。然后发送读取的命令,最后读取对应的值。再使用校准系数计算出最终的物理值。

STM32与MS5837压力传感器的I2C通讯_第5张图片

/*获取转换值,包括温度和压力*/
void GetConversionValue(uint8_t deviceAddress,float *pPres,float *pTemp,uint16_t *caliPara,uint16_t *semaphore,WriteCommandToMs5837Type WriteCommandToMs5837,ReadBytesFromMs5837Type ReadBytesFromMs5837)
{
  uint16_t senst1;        //C1压力灵敏度
  uint16_t offt1;         //C2压力补偿值
  uint16_t tcs;           //C3压力灵敏度温度系数
  uint16_t tco;           //C4压力补偿温度系数
  uint16_t tref;          //C5参考温度
  uint16_t tempsens;      //C6温度传感器温度系数

  /*从MS5837的PROM中读取校准数据*/
  if(*semaphore>0)
  {
    GetCalibrationData(deviceAddress,caliPara,WriteCommandToMs5837,ReadBytesFromMs5837);
    *semaphore=*semaphore-1;
  }
  senst1=caliPara[0];
  offt1=caliPara[1];
  tcs=caliPara[2];
  tco=caliPara[3];
  tref=caliPara[4];
  tempsens=caliPara[5];

  uint32_t digitalPressureValue;
  uint32_t digitalTemperatureValue;

  /*读取压力数据*/
 digitalPressureValue=ReadConversionFromMs5837(deviceAddress,COMMAND_CONVERTD1OSR4096,WriteCommandToMs5837,ReadBytesFromMs5837);

  Delayms(20);

  /*读取温度数据*/
 digitalTemperatureValue=ReadConversionFromMs5837(deviceAddress,COMMAND_CONVERTD2OSR4096,WriteCommandToMs5837,ReadBytesFromMs5837);

  /*对温度进行一阶修正*/
  int32_t dT;
  int32_t temp;
  dT=digitalTemperatureValue-tref*256;
  temp=(int32_t)(2000+dT*tempsens/pow(2,23));

  /*对压力进行一阶修正*/
  int64_t off;
  int64_t sens;
  int32_t pres;
  off=(int64_t)(offt1*pow(2,17)+(tco*dT)/pow(2,6));
  sens=(int64_t)(senst1*pow(2,16)+(tcs*dT)/pow(2,7));
  pres=(int32_t)((digitalPressureValue*sens/pow(2,21)-off)/pow(2,15));

  /*对温度和压力进行二阶修正*/
  int64_t ti=0;
  int64_t offi=0;
  int64_t sensi=0;
  int64_t off2=0;
  int64_t sens2=0; 

  if(temp<2000)
  {
    ti=(int64_t)(11*dT*dT/pow(2,35));
    offi=(int64_t)(31*(temp-2000)*(temp-2000)/pow(2,3));
    sensi=(int64_t)(63*(temp-2000)*(temp-2000)/pow(2,5));
   
    off2=off-offi;
    sens2=sens-sensi;
   
    temp=temp-(int32_t)ti;
    pres=(int32_t)((digitalPressureValue*sens2/pow(2,21)-off2)/pow(2,15));
  }

  if((-4000<=temp)&&(temp<=8500))
  {
    *pTemp=(float)temp/100.0;
  }

  if((1000<=pres)&&(pres<=120000))
  {
    *pPres=(float)pres/100.0;
  }
}

最终在STM32的I2C接口实现通讯时,实现2个WriteCommandToMs5837Type(uint8_t deviceAddress,uint8_t command);和ReadBytesFromMs5837Type(uint8_t deviceAddress,uint8_t *pData,uint16_t bytesNum);函数并调用就可以了,换做其他的平台也只需要重写这两个函数就能实现通讯了。

欢迎关注:

STM32与MS5837压力传感器的I2C通讯_第6张图片

你可能感兴趣的:(STM32研发,嵌入式开发,I2C,STM32,MS5837)