外设驱动库开发笔记18:MS5837压力变送器驱动
絕對壓力的檢測是常見的需求。在我們的系統中也常常會遇到。而MS5837壓力傳感器也是我們進場會采用的方案。在這篇里我們將討論并實現MS5837壓力傳感器的驅動。
1、功能概述
MS5837壓力傳感器是一種可用于電路板上,適用于檢測10-1200mbar壓力范圍的傳感器,靈敏度非常高,理論上能夠檢測到0.01mbar的壓力變化,實際使用過程中測試并無明顯的變化。
MS5837壓力傳感器采用I2C總線通訊,與MCU可以實現I2C通訊。硬件連接方式如下:
MS5837壓力傳感器擁有5類基本命令:復位、讀取出廠校準值、數據1轉換(壓力值數據)、數據2轉換(溫度值數據)和讀取ADC的轉換結果。具體分配如下:
因為MS5837的地址是固定的,所以一個I2C總線只能掛1個MS5837模塊。其設備地址固定為:0xEC。
2、驅動設計與實現
我們已經了解了MS5837的基本功能和操作方式。接下來我們就根據前面的分析實現MS5837的驅動。
2.1、對象定義
在使用該對象之前,我們需要定義對象,我們根據MS5837的屬性和操作來定義對象。
2.1.1、對象類型抽象
為了方便操作與復用,我們使用基于對象的操作。這里我們先來抽象MS5837壓力傳感器對象的類型,該類型包含了MS5837的必要屬性和對MS5837基本操作。
我們先來分析MS5837壓力傳感器對象的屬性。MS5837壓力傳感器使用的是I2C通訊接口,需要一個地址分辨總線上的不同設備,所以我們將I2C設備地址作為MS5837壓力傳感器對象的一個屬性。此外,在計算MS5837壓力傳感器測量的壓力、溫度值時需要使用6個校準參數,而且這些參數每臺設備都是不一樣的,所以我們將這些參數作為屬性來保存其值。
接下來我們再來分析MS5837壓力傳感器對象的操作。我們使用MS5837壓力傳感器時,需要向其寫命令和從其讀數據,而讀寫操作都依賴于具體的硬件平臺,所以我們將寫數據和讀數據作為對象的操作。此外,為控制時序,我們需要延時操作,而延時行為的實現亦依賴于具體的軟硬件平臺,所以我們將延時也作為對象的操作。
根據上述我們對MS5837壓力傳感器對象的分析,我們可以抽象MS5837壓力傳感器的對象類型為:
/* 定義MS5837對象類型 */ typedef struct MS5837Object {uint8_t devAddress;???????????????? //設備地址uint16_t caliData[6];??????? //校準數據float temperature;float pressure;void (*Write)(struct MS5837Object *ms,uint8_t command);/*向MS5837下發指令,指令格式均為1個字節*/void (*Read)(struct MS5837Object *ms,uint8_t *rData,uint16_t rSize);/*從MS5837讀取多個字節數據的值*/void (*Delayms)(volatile uint32_t nTime);???? //毫秒秒延時函數 }MS5837ObjectType;2.1.2、對象初始化
在使用之前,我們先要使用對象類型聲明對象,但聲明的對象只是一個變量,該對象變量在使用前必須初始化,所以我們定義了對象初始化函數。
/* 初始化MS5837對象 */ void MS5837Initialization(MS5837ObjectType *ms,MS5837Write write,MS5837Read read,MS5837Delayms delay) {if((ms==NULL)||(write==NULL)||(read==NULL)||(delay==NULL)){return;??}ms->Write=write;ms->Read=read;ms->Delayms=delay;ms->devAddress=0b11101100;ms->pressure=0.0;ms->temperature=0.0;ResetForMs5837(ms);GetCalibrationData(ms); }2.2、對象操作
完成了對象的聲明與初始化之后,我們就可以使用對象變量來操作對象了。關于MS5837的操作主要有:設備復位、校準值獲取、轉換值的讀取。下面將一一實現。
2.2.1、復位操作
復位操作在MS5837壓力傳感器有電時就可執行,但一般會在上電之后需要復位一下,以保持內存中的校準參數值是正確的。此外,當I2C的SDA引腳因未知原因出現阻塞時,復位能消除這種不確定性。復位操作只需要發送一條命令,其時序圖如下:
/*復位MS5837操作*/ void ResetForMs5837(MS5837ObjectType *ms) {uint8_t command=COMMAND_RESET;/*下發復位命令*/ms->SendCommand(ms,command); }2.2.2、讀取校準值
校準值是出廠時廠家校準的各種系數,每臺設備都有差異,是固定不變的,只需要一次讀取就可以了,共有6個系數,均為16為整數。首先發送讀系數的命令,然后讀取就可以了,每次讀取1個,分6次讀取。過程數據流如下圖所示:
/*讀取MS5837內存寄存器的數據*/ static uint16_t ReadPromFromMs5837(MS5837ObjectType *ms,uint8_t command) {/*下發讀取指定內存單元的命令*/ms->Write(ms,command);/*接收讀取的指定內存單元的值*/uint8_t promValue[2];ms->Read(ms,promValue,2);uint16_t result=(uint16_t)promValue[0];result=(result<<8)+(uint16_t)promValue[1];return result; }2.2.3、讀取轉換值
讀取轉換結果值是我們的目的,可以讀取溫度和壓力兩個量,不過一次只能讀一個。首先發送命令設定采集壓力還是溫度,并設定精度。然后發送讀取的命令,最后讀取對應的值。再使用校準系數計算出最終的物理值。
/*讀取MS5837ADC的轉換值*/ static uint32_t ReadConversionFromMs5837(MS5837ObjectType *ms,uint8_t command) {/*下發轉化對象及精度配置命令*/ms->Write(ms,command);ms->Delayms(10);/*下發讀取ADC的命令*/ms->Write(ms,COMMAND_ADC_READ);ms->Delayms(10);/*接收讀取的ADC轉換結果*/uint8_t adcValue[3];ms->Read(ms,adcValue,3);uint32_t result=(uint32_t)adcValue[0];result=(result<<8)+(uint32_t)adcValue[1];result=(result<<8)+(uint32_t)adcValue[2];return result; }這里獲取的只是ADC的數字碼值。我們想要得到溫度和壓力的物理量值還需要使用校準值,通過廠家提供的公式計算得到。
3、驅動的使用
在前面我們描述了MS5837壓力傳感器的基本情況,在此基礎上設計并實現了MS5837壓力傳感器對象的驅動程序。這一節我們將設計一個簡單的應用來驗證驅動設計是否符合要求。
3.1、聲明并初始化對象
使用基于對象的操作我們需要先得到這個對象,所以我們先要使用前面定義的MS5837壓力傳感器對象類型聲明一個MS5837壓力傳感器對象變量,具體操作格式如下:
MS5837ObjectType ms5837;
聲明了這個對象變量并不能立即使用,我們還需要使用驅動中定義的初始化函數對這個變量進行初始化。這個初始化函數所需要的輸入參數如下:
MS5837ObjectType *ms,MS5837對象
MS5837Write write,向MS5837寫數據函數指針
MS5837Read read,從MS5837讀數據函數指針
MS5837Delayms delayms,毫秒延時函數指針
對于這些參數,對象變量我們已經定義了。我們需要重點關注幾個函數指針,首先要定義這幾個函數,并將函數指針作為參數。這幾個函數的類型如下:
/*向MS5837下發指令,指令格式均為1個字節*/ typedef void (*MS5837Write)(struct MS5837Object *ms,uint8_t command);/*從MS5837讀取多個字節數據的值*/ typedef void (*MS5837Read)(struct MS5837Object *ms,uint8_t *rData,uint16_t rSize);/*毫秒秒延時函數*/ typedef void (*MS5837Delayms)(volatile uint32_t nTime);對于這幾個函數我們根據樣式定義就可以了,具體的操作可能與使用的硬件平臺有關系。片選操作函數用于多設備需要軟件操作時,如采用硬件片選可以傳入NULL即可。具體函數定義如下:
/*通過I2C1接口下發命令*/ static void SendCommandToMS5837(MS5837ObjectType *ms,uint8_t command) {HAL_I2C_Master_Transmit(&ms5837hi2c,ms->devAddress,&command,1,1000); }/*通過I2C1接口讀取數據*/ static void GetDatasFromMS5837(MS5837ObjectType *ms,uint8_t *rData,uint16_t rSize) {HAL_I2C_Master_Receive(&ms5837hi2c,ms->devAddress,rData,rSize,1000); }對于延時函數我們可以采用各種方法實現。我們采用的STM32平臺和HAL庫則可以直接使用HAL_Delay()函數。于是我們可以調用初始化函數如下:
MS5837Initialization(&ms5837,SendCommandToMS5837,GetDatasFromMS5837,HAL_Delay);
3.2、基于對象進行操作
我們定義了對象變量并使用初始化函數給其作了初始化。接著我們就來考慮操作這一對象獲取我們想要的數據。我們在驅動中已經將獲取數據并轉換為轉換值的比例值,接下來我們使用這一驅動開發我們的應用實例。
/*獲取壓力變送器數據*/ void MS5837GetMeasureData(void) {float pressure=0.0;float temperature=0.0;GetMS5837ConversionValue(&ms5837,MS5837_OSR8192,MS5837_OSR8192);pressure=ms5837.pressure;temperature=ms5837.temperature;}4、應用總結
我們已經實現了MS5837壓力傳感器的驅動程序,也設計了一個簡單的應用來驗證這一驅動程序。驗證的結果與我們預期一樣,得到了我們需要的數據。我們也曾將這一驅動應用于實際項目,效果也是令人滿意的。
使用驅動是需要注意,MS5837壓力傳感器雖然采用了I2C接口,但它的地址是固定的,所以一條總線上只能有一臺MS5837壓力傳感器。所以在驅動中地址是固化在驅動程序中不可修改的。
源碼下載:https://github.com/foxclever/ExPeriphDriver
歡迎關注:
?
總結
以上是生活随笔為你收集整理的外设驱动库开发笔记18:MS5837压力变送器驱动的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: spark sql hbase java
- 下一篇: LwIP应用开发笔记之一:LwIP无操作