MS5607 气压计调试记录

MS5607气压计调试过程记录

采用 SPI通讯方式驱动MS5607,主控用的是STM32F777
程序是利用STM32CUBEMX生成的 驱动 根据芯片手册和一些参考资料自己写的,数据暂时看是没问题的。
没有测试环境 没有系统测试过,数值验证没问题。

1,上电初始化MS5607:主要是复位芯片 然后读出prom校准数据(C1-C6)

向spi总线发送0x1e,复位芯片

void MX56XX_Ba_Reset(void)
{
	uint8_t _cmd=0x1e;
	
	MS5607_SPI_CS(0);
	MS56XX_ReadWriteByte(_cmd);    
	MS5607_SPI_CS(1);
	delay_xms(3);

}

然后读取prom校准数据,这个数据是厂商写好的 ,只需要开机上电读取一次就行。
prom read地址从0xA0到0xAE 。

image.png
读prom

void MX56XX_Read_Prom_Data(void)
{
	uint8_t _cmd;
	uint8_t _ctr;
	uint8_t  _buff[2];	

	_cmd = 0xa0;   //prom首地址

	for(_ctr = 0;_ctr<8;_ctr++)  
	{
		MS5607_SPI_CS(0);	
		MS56XX_ReadWriteByte(_cmd);	
        _buff[0] = MS56XX_ReadWriteByte(0XFF); 
	    _buff[1] = MS56XX_ReadWriteByte(0XFF);
		Cal_C[_ctr]=(_buff[0]<<8)+_buff[1];		
        _cmd += 0x02;		  
		MS5607_SPI_CS(1);
	}
}

这里有个地方需要注意 ,下图是prom的内存映射。
image.png

之前读取的数据一直不对,以为数据C1的地址是0xa0,后来看了手册后才知道还有制造商的信息。
从prom的内存映射可以看出,prom的首地址 存放的是制造商的数据和设备信息 ,地址 1-6是校准数据c1-c6,地址7是4bit的crc校验信息。
所以 这就是循环读取8次的原因,然后Cal_C[1]~Cal_C[6] 就对应了的C1~C6的校准数据。Cal_C[7]是CRC校验数据,可以进行验证通信使用。

image.png

还有就是C1~C6的数据是16位的 ,我用的SPI读取是读一个字节,所以 连续读取两次在组成16位的数据在用就可以了。

2 以上初始化完成以后,接下来就是循环读取D1,D2的值 然后用公式计算 数字温度和压强。

读地址是ADC Rread 0x00。
D1 的分辨率 OSR=4096 地址 0x48
D2的分辨率 OSR=4096 地址 0x58
image.png

计算公式和变量信息。
image.png

读D1

uint8_t  _presbuf[3];
uint32_t MS56XX_Do_Conversion_Pres(void)  //数据读取
{
	uint8_t  _cmd=0X48;
	uint32_t _D1;
//	uint8_t  _buf[4];
	MS5607_SPI_CS(0);
	MS56XX_ReadWriteByte(_cmd);    //0x48 -->D1  OSR=4096
	MS5607_SPI_CS(1);
		
	MS56XX_Read_Buf(0x00,_presbuf,3);
	_D1=(_presbuf[0]<<16)+ (_presbuf[1]<<8) +(_presbuf[2]);//读取adc值
//_D1=_buf[0]<<24 | buf[1]<<16 |buf[2]<<8 | buf[3];//读取adc值

	return _D1;
}

读D2


uint8_t  _tempbuf[3];
uint32_t MS56XX_Do_Conversion_Temp(void)  //数据读取
{
	uint8_t  _cmd=0X58;

	uint32_t _D2;
	MS5607_SPI_CS(0);
	MS56XX_ReadWriteByte(_cmd);  //0x58 -->D2  OSR=4096
	MS5607_SPI_CS(1); 	
	MS56XX_Read_Buf(0x00,_tempbuf,3);
	_D2=(_tempbuf[0]<<16)+ (_tempbuf[1]<<8) +(_tempbuf[2]);//读取adc值	
	return _D2;
}

//读取并计算数字温度


char MS56XX_GetTemperature (void)     //计算温度
{
	D2_Temp = MS56XX_Do_Conversion_Temp ( );      //循环读取 D1 D2

	if(D2_Temp == 0)
		return 0;
	
		delay_ms ( 10 );

	if(D2_Temp > (  ( uint32_t ) Cal_C[5] * (0x00000001 << 8) ))
		dT	= D2_Temp - (  ( uint32_t ) Cal_C[5] * (0x00000001 << 8) );  //公式 dT = D2 - TREF = D2 - C5 * 2^8
	else
	{
		dT	= (  ( uint32_t ) Cal_C[5] * (0x00000001 << 8) ) - D2_Temp;   	
		dT *= -1;
	}
	Temperature	= 2000 + ( dT * Cal_C[6] ) / (0x00000001 << 23); //算出温度值的100倍,2001表示20.01°  公式TEMP =20°C + dT * TEMPSENS =2000 + dT * C6 / 2^23

	if(Temperature<-4000) Temperature=-4000;
	if(Temperature>8500) Temperature=8500;
	return 1;
}

读取并计算数字气压

char MS56XX_GetPressure (void)  //计算温度补偿压力
{
	D1_Pres = MS56XX_Do_Conversion_Pres ( );   //循环读取 D1 D2

	if(D1_Pres == 0)
		return 0;
	
		delay_xms ( 10 );
	
	OFF	=  ( ( int64_t )Cal_C[2] * (0x00000001 << 17) ) + ( ( int64_t ) Cal_C[4] * dT ) / 64.0;    //公式 OFF = OFFT1 + TCO *dT = C2 *2^17 +(C4 *dT )/ 2^6
	SENS 		= ( ( int64_t ) Cal_C[1] * (0x00000001 << 16) ) + ( ( int64_t ) Cal_C[3] * dT ) / 128.0; //公式SENS = SENST1 + TCS* dT= C1 * 2^16 + (C3 * dT )/ 2^7

	//温度补偿部分    逻辑看芯片手册   
	
	if ( Temperature < 2000 ) // second order temperature compensation when under 20 degrees C
	{
		T2 = ( dT * dT ) / (( uint64_t )0x0000000001 << 31);
		OFF2 		= 61 *  (( Temperature - 2000 ) * ( Temperature - 2000 )) / 16;
		SENS2		= 2 * (( Temperature - 2000 ) * ( Temperature - 2000 )) ;
		if ( Temperature < -1500 )
		{
			OFF2 		= OFF2 + 15 * (( Temperature + 1500 ) * ( Temperature + 1500 )) ;
			SENS2		= SENS2 + 8 * (( Temperature + 1500 ) * ( Temperature + 1500 )) ;
		}
	}
	else		//(Temperature > 2000)
	{
		T2 = 0;
		OFF2 		= 0;
		SENS2		= 0;
	}

	Temperature = Temperature - T2;
	OFF			= OFF - OFF2;
	SENS 		= SENS - SENS2;
	
	
	Pressure = ( D1_Pres * SENS / (0x00000001 << 21) - OFF ) / (0x00000001 << 15); //公式 P = D1 * SENS - OFF = (D1 * SENS / 2^21 - OFF) / 2^15

	Ms5607.Temperature=(float)Temperature/100;  		//单位  ℃     
	Ms5607.Pressure=(float)Pressure/100;           //单位  mbar 

	if(Ms5607.Temperature<-40) Ms5607.Temperature=-40;
	if(Ms5607.Temperature>85)  Ms5607.Temperature=85;
	if(Ms5607.Pressure<10) 		 Ms5607.Pressure=10;
	if(Ms5607.Pressure>1200) 	 Ms5607.Pressure=1200;

	printf("Pressure=%4f mbar\r\n",Ms5607.Pressure);
		
	return 1;
}

温度补偿部分的逻辑
image.png

补充1

/********************************************************************************

** 1MPa=1000,000Pa=10bar=10000mbar hPa(百帕)=mbar(毫巴)。

** 每提高12m,大气压下降1mmHg(1毫升水银柱)或者每上升9m,大气压降低100Pa。
** 例如已知气压970hpa,如何求出海拔是多少? 标准大气压为1013.25百帕(hpa)
** 所以,海拔高度为h=(1013.25-970)*9=389.25(米)。

********************************************************************************/
补充2

image.png

SPI时序:在分辨率=4096的是时候 adc的转换时间是8.22ms 所以要留够延时时序。
D1和D2虽然变量定义是32的 但是实际读取字节的时候是读取24bit的数据,也就是3个字节的数据。

//SPI 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
uint8_t MS56XX_ReadWriteByte(uint8_t TxData)
{
  uint8_t Rxdata;
  HAL_SPI_TransmitReceive(&hspi2,&TxData,&Rxdata,1, 1000);   
	
  return Rxdata;                              //返回收到的数据               
}


uint8_t MS56XX_Read_Buf(uint8_t reg ,uint8_t *pbuf,uint8_t len)//参数说明  发送寄存器位置   读取指定长度的数据 放在pbuf里
{
  u8 status,_ctr;
		
	MS5607_SPI_CS(0);
	delay_xms(9);//预留给ad转换时间,因为osr=4096分辨率   时序上转换时间约为8.2ms
  status=MS56XX_ReadWriteByte(reg);  //发送寄存器位置  
	
	for(_ctr=0;_ctr<len;_ctr++) 
	{
    pbuf[_ctr] = MS56XX_ReadWriteByte(0XFF); 
	}
   
	MS5607_SPI_CS(1);
	return status;//返回收到的数据               
}



uint8_t MS56XX_Write_Buf(u8 reg, u8 *pBuf, u8 len)//参数说明  发送寄存器位置   写指定长度的数据 
{
		u8 status,_ctr;
	
		MS5607_SPI_CS(0);                    //使能 SPI 传输
		status = MS56XX_ReadWriteByte(reg);   //发送寄存器值(位置),并读取状态值
	
		for(_ctr=0; _ctr<len; _ctr++) 
		{
			MS56XX_ReadWriteByte(*pBuf++);    //写入数据
		}
			
		MS5607_SPI_CS(1);                    //关闭 SPI 传输
		return status;                      //返回读到的状态值
}

结果
image.png

笔者在调试时,参考了以下博文,向这些博主及作者表示感谢!

MS56XX:

https://blog.csdn.net/zhxlx/article/details/93984496

https://bbs.21ic.com/icview-1722818-1-3.html

https://blog.csdn.net/xian_z/article/details/76461696

SPI:
https://www.jianshu.com/p/5de187bf5b75

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值