很多時(shí)候我們需要檢測(cè)流量和壓力這些參數(shù),比如我們要檢測(cè)大氣壓,或者通過測(cè)量差壓來獲得輸送流體的流量等,都需要用到壓力傳感器。這一篇我們就來討論MS4515DO壓力傳感器的數(shù)據(jù)獲取。
1、功能概述
??MS4515DO是TE公司推出的一款基于PCB安裝的小型陶瓷基壓力傳感器。該傳感器采用最新的CMOS傳感器調(diào)節(jié)電路,制造出一種低成本、高性能的數(shù)字輸出壓力(14bit)和溫度(11bit)傳感器,以滿足OEM客戶最嚴(yán)格的要求。
??MS4515DO完全校準(zhǔn)和溫度補(bǔ)償,總誤差帶在補(bǔ)償范圍內(nèi)小于1.0%。該傳感器采用直流3.3V或5.0V單電源供電模式,對(duì)外接口采用I2C總線或三線SPI的模式。其結(jié)構(gòu)圖如下:
??MS4515DO和MS4525DO擁有相同的功能和模式,區(qū)別只在于輸出的物理量單位不同而已。它們都擁有可以檢測(cè)差壓和絕壓的型號(hào),但操作是完全一樣的,所以本篇的討論事實(shí)上適用于相關(guān)系列的全部型號(hào)的應(yīng)用。
1.1、MS4515DO的I2C地址
??作為I2C接口的設(shè)備都會(huì)有一個(gè)設(shè)備地址,MS4515DO壓力傳感器也不例外。而MS4515DO和MS4525DO系列傳感器的I2C地址在出廠時(shí)已特定寫入,并根據(jù)型號(hào)中的字母來指示其地址設(shè)定。具體如下:
??預(yù)設(shè)的設(shè)備地址是7位的,不包含讀寫位的指示。我們使用時(shí)需要將其左移一位并根據(jù)讀寫操作來定義讀寫位,0為寫,1為讀。
1.2、數(shù)據(jù)輸出格式
??在I2C通訊模式下,MS4515DO和MS4525DO傳感器有四個(gè)I2C讀取命令,分別為:Read_MR、Read_DF2、Read_DF3和Read_DF4。這四個(gè)命令可以獲取不同的數(shù)據(jù),這些命令的具體報(bào)文格式定義如下圖:
??所以我們想要獲取MS4515DO和MS4525DO傳感器的數(shù)據(jù)就需要通過上述命令來實(shí)現(xiàn)。從上述的命令報(bào)文格式可以看出,這些命令在本質(zhì)上是沒有差別的,都多少數(shù)據(jù)完全由主機(jī)來控制,也就是我們開發(fā)的驅(qū)動(dòng)程序來控制。事實(shí)上,我們只需要考慮Read_DF4這個(gè)命令就可以涵蓋所有想要的數(shù)據(jù)。
??我們需要注意的是,上述的報(bào)文中有兩位存儲(chǔ)的是狀態(tài)信息,該狀態(tài)信息表示獲取的數(shù)據(jù)是最新的數(shù)據(jù)還是舊數(shù)據(jù)或者錯(cuò)誤報(bào)警。通過判斷這個(gè)數(shù)據(jù)可以決定我們?cè)跀?shù)據(jù)解析時(shí)如何處理相應(yīng)的報(bào)文。
2、驅(qū)動(dòng)設(shè)計(jì)與實(shí)現(xiàn)
??我們已經(jīng)了解了MS4515DO和MS4525DO傳感器的結(jié)構(gòu)、接口方式、設(shè)備地址以及數(shù)據(jù)輸出格式。接下來我們就可以考慮如何實(shí)現(xiàn)MS4515DO和MS4525DO傳感器的驅(qū)動(dòng)程序了。
2.1、對(duì)象定義
??我們依然還是先來考慮MS4515DO和MS4525DO傳感器的對(duì)象定義。我們定義一個(gè)對(duì)象無非考慮屬性和操作兩個(gè)部分。
??首先我們來考慮MS4515DO和MS4525DO傳感器對(duì)象的屬性。首先MS4515DO和MS4525DO傳感器采用I2C接口通訊,所以每臺(tái)都有一個(gè)設(shè)備地址。這個(gè)地址標(biāo)識(shí)了I2C總線上該設(shè)備的唯一性,所以我們將設(shè)備地址作為MS4515DO和MS4525DO傳感器對(duì)象的一個(gè)屬性。對(duì)于MS4515DO和MS4525DO傳感器來說存在多種類型,而不同的類型對(duì)應(yīng)不同的數(shù)據(jù)計(jì)算方式,所以針對(duì)某一具體實(shí)例,我們需要記錄它的類型,所以我們?yōu)槠涠x一個(gè)類型屬性。我們?cè)谟?jì)算壓力值時(shí),不同的量程最后得到的壓力值與測(cè)量量程有關(guān),所以我們還需要記錄實(shí)例的量程上下限,所以將這兩個(gè)數(shù)據(jù)也定義為對(duì)象的屬性。為了操作方便我們將最終得到的溫度和壓力數(shù)據(jù)也都作為對(duì)象的屬性。
??從前面的描述中,我們知道MS4515DO和MS4525DO傳感器的數(shù)據(jù)輸出格式是固定的,這為我們解析這一數(shù)據(jù)提供了思路。我們將讀出的4個(gè)字節(jié)與我們想要得到的數(shù)據(jù)組成聯(lián)合體,利用結(jié)構(gòu)體和聯(lián)合體在內(nèi)存中的關(guān)系可以方便的解析數(shù)據(jù)對(duì)象,如下圖所示:
??這些個(gè)數(shù)據(jù)即是我們想要的先要得到的,同時(shí)他們也記錄了MS4515DO和MS4525DO傳感器對(duì)象當(dāng)前的狀態(tài),所以我們將其也作為對(duì)象的屬性。
??其次我們來考慮MS4515DO和MS4525DO傳感器對(duì)象的操作。我們需要將對(duì)象的哪些行為定義為操作呢?一般的我們考慮那些不能直接實(shí)現(xiàn),而是要依賴特定的軟硬件平臺(tái)才能實(shí)現(xiàn)的對(duì)象行為。我們需要向MS4515DO和MS4525DO傳感器發(fā)送命令,也需要從傳感器獲取對(duì)象,而無論讀還是寫都是依賴于具體的軟硬件平臺(tái)才能去定的,所以我們將向傳感器寫信息和從傳感器讀信息作為對(duì)象的2個(gè)操作。為了控制時(shí)序,我們一般需要演示處理函數(shù),而演示處理函數(shù)的實(shí)現(xiàn)也是依賴于具體的軟硬件平臺(tái)的,所以我們將延時(shí)函數(shù)定義為對(duì)象的一個(gè)操作。
??我們分析了MS4515DO和MS4525DO傳感器對(duì)象可能的屬性和操作。根據(jù)前述的分析,我們可以定義MS4515DO和MS4525DO傳感器對(duì)象的類型如下:
/* 定義MS45x5DO對(duì)象類型 */typedef struct MS45x5DOObject {
uint8_t devAddress; //設(shè)備地址
union {
struct {
uint16_t pressure:14; uint16_t status:2; uint16_t insignificance:5; uint16_t temperature:11;
}pData; uint8_t rData[4];
}msData; //讀出的數(shù)值
MS45x5DOType type; //MS4515DO的類型
float pUpperRange; //壓力量程上限
float pLowerRange; //壓力量程下限
float fTemperature; //計(jì)算的溫度值
float fPressure; //計(jì)算的壓力值
void (*Write)(struct MS45x5DOObject *ms,uint8_t *wData,uint16_t wSize); //向MS45x5DO寫數(shù)據(jù)
void (*Read)(struct MS45x5DOObject *ms,uint8_t *rData,uint16_t rSize); //從MS45x5DO讀數(shù)據(jù)
void (*Delayms)(volatile uint32_t nTime); //毫秒秒延時(shí)函數(shù)}MS45x5DOObjectType;
??我們定義了MS4515DO和MS4525DO傳感器對(duì)象的類型,使用該類型我們可以定義我們想要的對(duì)象變量,但對(duì)象變量需要進(jìn)行必要的配置才能真正的實(shí)例化,這個(gè)過程我們將其稱之為對(duì)象的初始化。
/* 初始化MS45x5DO對(duì)象 */void MS45x5DOInitialization(MS45x5DOObjectType *ms, //MS5837對(duì)象
uint8_t devAddress, //設(shè)備地址
MS45x5DOType type, //MS4515DO的類型
float pMax, //壓力量程上限
float pMin, //壓力量程下限
MS45x5DOWrite write, //向MS45x5DO寫數(shù)據(jù)函數(shù)指針
MS45x5DORead read, //從MS45x5DO讀數(shù)據(jù)函數(shù)指針
MS45x5DODelayms delayms //毫秒延時(shí)函數(shù)指針
){ if((ms==NULL)||(write==NULL)||(read==NULL)||(delayms==NULL))
{ return;
}
ms->Write=write;
ms->Read=read;
ms->Delayms=delayms;
if((devAddress==0x28)||(devAddress==0x36)||(devAddress==0x46)||((0x48<=devAddress)&&(devAddress<=0x51)))
{
ms->devAddress=(devAddress<<1);
} else if((devAddress==0x50)||(devAddress==0x6C)||(devAddress==0x8C)||((0x48<=(devAddress/2))&&((devAddress/2)<=0x51)))
{
ms->devAddress=devAddress;
} else
{
ms->devAddress=0x00;
}
ms->type=type;
ms->fPressure=0.0;
ms->fTemperature=0.0;
ms->msData.rData[0]=0;
ms->msData.rData[1]=0;
ms->msData.rData[2]=0;
ms->msData.rData[3]=0;
if((fabs(pMax)<=0.0000001)&&(fabs(pMin)<=0.0000001))
{
ms->pUpperRange=100.0;
ms->pLowerRange=0.0;
} else
{
ms->pUpperRange=pMax;
ms->pLowerRange=pMin;
}
}
2.2、對(duì)象操作
??我們已經(jīng)可以得到一個(gè)對(duì)象變量并將它實(shí)例化,我們還需要考慮它的操作問題。對(duì)于MS4515DO和MS4525DO傳感器來說其操作比較簡(jiǎn)單,最主要的操作包括數(shù)據(jù)獲取和地址設(shè)定。
2.2.1、獲取數(shù)據(jù)
??對(duì)于我們來說獲取MS4515DO和MS4525DO傳感器的測(cè)量數(shù)據(jù)是我們的主要目的。我們可以從MS4515DO和MS4525DO傳感器獲取壓力和溫度數(shù)據(jù),其測(cè)量范圍與輸出數(shù)據(jù)的對(duì)應(yīng)關(guān)系如下圖所示:
??根據(jù)上表中的數(shù)據(jù)對(duì)應(yīng)關(guān)系,我們可以編寫獲取MS4515DO和MS4525DO傳感器的數(shù)據(jù)并解析的函數(shù)。
/*獲取轉(zhuǎn)換值,包括溫度和壓力*/void GetMS45x5DOConversionValue(MS45x5DOObjectType *ms){ uint8_t rData[4]={0,0,0,0}; float maxCount=16383; float minCount=0;
if(ms->type==MS45x5DO_TypeA)
{
maxCount=13106;
minCount=1638;
} else
{
maxCount=14746;
minCount=819;
}
ms->Read(ms,rData,4);
ms->msData.rData[0]=rData[1];
ms->msData.rData[1]=rData[0];
ms->msData.rData[2]=rData[3];
ms->msData.rData[3]=rData[2];
if(ms->msData.pData.status!=MS45x5DO_Fault)
{
ms->fPressure=(((float)ms->msData.pData.pressure-minCount)/maxCount)*(ms->pUpperRange-ms->pLowerRange)+ms->pLowerRange;
ms->fTemperature=((float)ms->msData.pData.temperature/2047.0)*200.0-50.0;
}
}
2.2.2、地址設(shè)置
??關(guān)于MS4515DO和MS4525DO傳感器,在出廠時(shí)已經(jīng)設(shè)定了設(shè)備地址并在型號(hào)編碼中給予指示。但在一些特殊情形下我們可能需要修改它的設(shè)備地址,這就需要用到MS4515DO和MS4525DO傳感器的地址修改操作。
/*修改MS45x5DO的設(shè)備地址*/void ModifyMS45x5DODecAddress(MS45x5DOObjectType *ms,uint8_t newAddress){ uint8_t eepromByte[3]; uint16_t eepromTemp=0x00;
//第1步、進(jìn)入命令模式
eepromByte[0]=0xA0;
eepromByte[1]=0x00;
eepromByte[2]=0x00;
ms->Write(ms,eepromByte,3);
//第2步、發(fā)送讀EEPROM命令
eepromByte[0]=0x02;
eepromByte[1]=0x00;
eepromByte[2]=0x00;
ms->Write(ms,eepromByte,3);
//第3步、獲取EEPROM的值
ms->Read(ms,eepromByte,3);
//第4步、修改為新地址
if(eepromByte[0]==0x5A)
{
eepromTemp=(eepromByte[1]<<8)+eepromByte[2];
eepromTemp=(eepromTemp&0xE007)+0xC00+(newAddress<<3);
eepromByte[1]=(uint8_t)((eepromTemp&0xFF00)>>8);
eepromByte[1]=(uint8_t)(eepromTemp&0x00FF);
} else
{ return;
}
//第5步、將新地址寫入EEPROM
eepromByte[0]=0x02;
ms->Write(ms,eepromByte,3);
//第6步、退出命令模式
eepromByte[0]=0x80;
eepromByte[1]=0x00;
eepromByte[2]=0x00;
ms->Write(ms,eepromByte,3);
}
3、驅(qū)動(dòng)的使用
??我們已經(jīng)設(shè)計(jì)并實(shí)現(xiàn)了MS4515DO和MS4525DO壓力傳感器的驅(qū)動(dòng)程序。接下來我們將簡(jiǎn)單的說明如何使用這一驅(qū)動(dòng),并設(shè)計(jì)一個(gè)簡(jiǎn)單的示例驗(yàn)證這一驅(qū)動(dòng)程序的正確性。
3.1、聲明并初始化對(duì)象
??我們是基于對(duì)象設(shè)計(jì)的MS4515DO和MS4525DO壓力傳感器的驅(qū)動(dòng)程序,所以在使用驅(qū)動(dòng)時(shí),我們需要先聲明一個(gè)對(duì)象變量,然后基于該對(duì)象變量來實(shí)現(xiàn)具體的對(duì)象操作。我們先聲明對(duì)象如下:
MS45x5DOObjectType msDP;
??聲明了這個(gè)對(duì)象變量之后,我們還需要使用初始化函數(shù)對(duì)其進(jìn)行初始化方可使用。這一初始化函數(shù)擁有8個(gè)參數(shù):
MS45x5DOObjectType *ms, //MS5837對(duì)象uint8_t devAddress, //設(shè)備地址MS45x5DOType type, //MS4515DO的類型float pMax, //壓力量程上限float pMin, //壓力量程下限MS45x5DOWrite write, //向MS45x5DO寫數(shù)據(jù)函數(shù)指針MS45x5DORead read, //從MS45x5DO讀數(shù)據(jù)函數(shù)指針MS45x5DODelayms delayms //毫秒延時(shí)函數(shù)指針
??第一個(gè)參數(shù)正是我們要初始化的對(duì)象變量。第二個(gè)參數(shù)為我們所要操作的MS4515DO對(duì)象的設(shè)備地址。第三個(gè)參數(shù)是MS4515DO對(duì)象的具體類型,根據(jù)實(shí)際設(shè)備選擇枚舉即可。第四和第五個(gè)參數(shù)是該對(duì)象的物理量量程,根據(jù)具體對(duì)象而定。后面三個(gè)參數(shù)是實(shí)現(xiàn)對(duì)象操作的函數(shù)指針。這三個(gè)函數(shù)指針需要我們根據(jù)具體的軟硬件平臺(tái)來實(shí)現(xiàn)。它們的原型如下:
/*向MS45x5DO下發(fā)指令,指令格式均為1個(gè)字節(jié)*/typedef void (*MS45x5DOWrite)(struct MS45x5DOObject *ms,uint8_t *wData,uint16_t wSize);/*從MS45x5DO讀取多個(gè)字節(jié)數(shù)據(jù)的值*/typedef void (*MS45x5DORead)(struct MS45x5DOObject *ms,uint8_t *rData,uint16_t rSize);/*毫秒秒延時(shí)函數(shù)*/typedef void (*MS45x5DODelayms)(volatile uint32_t nTime);
??我們根據(jù)函數(shù)原型定義,在具體的實(shí)現(xiàn)平臺(tái)上實(shí)現(xiàn)它們,如我們?cè)?a href="http://ttokpm.com/v/tag/751/" target="_blank">STM32平臺(tái)上可以實(shí)現(xiàn)如下:
/ 向MS45x5DO下發(fā)指令,指令格式均為1個(gè)字節(jié) /
static void WriteToDP(MS45x5DOObjectType *ms,uint8_t *wData,uint16_t wSize)
{
HAL_I2C_Master_Transmit(&hi2c2,ms->devAddress,wData,wSize,1000);
}
/* 從MS45x5DO讀取多個(gè)字節(jié)數(shù)據(jù)的值* /
static void ReadFromDP(MS45x5DOObjectType *ms,uint8_t *rData,uint16_t rSize)
{
HAL_I2C_Master_Receive(&hi2c2,ms->devAddress,rData, rSize, 1000);
}
  延時(shí)函數(shù)我們可以直接使用HAL庫中的HAL_Delay也可以自己編寫,在HAL庫中HAL_Delay是一個(gè)弱化定義的函數(shù),我們可以重寫這一函數(shù)來實(shí)現(xiàn)不同的應(yīng)用需求。到這里我們就可以使用對(duì)象初始化函數(shù)來初始化前面聲明的對(duì)象變量了。具體如下:
```C++MS45x5DOInitialization(&msDP, //MS5837對(duì)象
0x28, //設(shè)備地址
MS45x5DO_TypeA, //MS4515DO的類型
DPUpperRange, //壓力量程上限
DPLowerRange, //壓力量程下限
WriteToDP, //向MS45x5DO寫數(shù)據(jù)函數(shù)指針
ReadFromDP, //從MS45x5DO讀數(shù)據(jù)函數(shù)指針
HAL_Delay //毫秒延時(shí)函數(shù)指針
);
3.2、基于對(duì)象進(jìn)行操作
??完成了對(duì)象的初始化后,我們就可以基于對(duì)象來實(shí)現(xiàn)相應(yīng)的操作了。如我們使用驅(qū)動(dòng)獲取msDP對(duì)象的差壓數(shù)據(jù)如下:
/*差壓數(shù)據(jù)獲取*/void GetFlowDPDatas(void){
GetMS45x5DOConversionValue(&msDP);
aPara.phyPara.dPressure =msDP.fPressure;
aPara.phyPara.dTemperature=msDP.fTemperature;
}
4、應(yīng)用總結(jié)
??我們?cè)O(shè)計(jì)并實(shí)現(xiàn)了MS4515DO和MS4525DO壓力傳感器對(duì)象的驅(qū)動(dòng)程序,并基于驅(qū)動(dòng)程序?qū)崿F(xiàn)了一個(gè)簡(jiǎn)單的測(cè)試實(shí)例,獲得的結(jié)果如下:
??從上述兩圖中我們可以知道我們的驅(qū)動(dòng)程序是正確的。事實(shí)上這一驅(qū)動(dòng)已應(yīng)用于我們的流量測(cè)量設(shè)備中,實(shí)現(xiàn)的效果良好。
評(píng)論
查看更多