STM32应用实例六:与MS5837压力传感器的I2C通讯
MS5837壓力傳感器是一種可用于電路板上,適用于檢測10-1200mbar壓力范圍的傳感器,靈敏度非常高,理論上能夠檢測到0.01mbar的壓力變化,實際使用過程中測試并無明顯的變化。
MS5837采用I2C總線通訊,與STM32的MCU可以實現I2C通訊。硬件連接方式如下:
MS5837只有5個基本命令:復位、讀取出廠校準值、數據1轉換(壓力值數據)、數據2轉換(溫度值數據)和讀取ADC的轉換結果。具體分配如下:
?
因為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)復位操作
復位操作的數據流如下圖所示,只需要發送一條命令就可完成:
?
/*復位MS5837操作*/void ResetForMs5837(uint8_t deviceAddress,WriteCommandToMs5837Type WriteCommandToMs5837){uint8_t command=COMMAND_RESET;/*下發復位命令*/WriteCommandToMs5837(deviceAddress,command);}(2)讀取校準值
校準值是出廠時廠家校準的各種系數,每臺設備都有差異,是固定不變的,只需要一次讀取就可以了,共有6個系數,均為16為整數。首先發送讀系數的命令,然后讀取就可以了,每次讀取1個,分6次讀取。過程數據流如下圖所示:
?
/*從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)讀取轉換值
讀取轉換結果值是我們的目的,可以讀取溫度和壓力兩個量,不過一次只能讀一個。首先發送命令設定采集壓力還是溫度,并設定精度。然后發送讀取的命令,最后讀取對應的值。再使用校準系數計算出最終的物理值。
?
/*獲取轉換值,包括溫度和壓力*/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);函數并調用就可以了,換做其他的平臺也只需要重寫這兩個函數就能實現通訊了。
轉載于:https://www.cnblogs.com/foxclever/p/6533907.html
總結
以上是生活随笔為你收集整理的STM32应用实例六:与MS5837压力传感器的I2C通讯的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 性能调优之:缓存
- 下一篇: java面向对象编程知识点总结