MS5803壓力傳感器支持SPI和I2C總線通訊,擁有24位AD轉(zhuǎn)換。能夠同時(shí)獲得壓力值和溫度值,其中壓力測(cè)量范圍為10-1100mbar,溫度的測(cè)量范圍是-40-85攝氏度。各引腳功能及參數(shù)如下: 傳感器內(nèi)部結(jié)構(gòu)圖如下: 通訊協(xié)議的選擇通過(guò)PS引腳來(lái)設(shè)置: PS引腳電位 | 通訊模式 | 使用的引腳 | 高電平 | I2C | SDA, SCL, CSB | 低電平 | SPI | SDI, SDO, SCLK, CSB |
在SPI模式下,SCLK作為外部輸入時(shí)鐘,SDI作為串行數(shù)據(jù)輸入,支持Mode0和Mode3的時(shí)鐘極性和相位。傳感器的響應(yīng)數(shù)據(jù)輸出為SDO引腳,片選信號(hào)為CSB引腳。界限示意圖如下: 在I2C模式下,SCLK為外部串行時(shí)鐘輸入,SDA位串行數(shù)據(jù)通訊。CSB引腳作為地只選擇,可以鏈接到VDD或者GND,這也意味著MS5803可以在一條I2C總線接兩個(gè)設(shè)備。在CSP接高電平時(shí),地址為0x76(1110110 b),而CSB接低電平時(shí),地址為0x77 (1110111 b)這個(gè)地址是高七位,最后以為有讀寫(xiě)命令來(lái)決定。實(shí)現(xiàn)寫(xiě)命令時(shí),最后一位為0,實(shí)現(xiàn)讀命令時(shí),最后一位為1。 MS5803擁有5個(gè)基本命令:復(fù)位、讀取出廠校準(zhǔn)值、數(shù)據(jù)1轉(zhuǎn)換(壓力值數(shù)據(jù))、數(shù)據(jù)2轉(zhuǎn)換(溫度值數(shù)據(jù))和讀取ADC的轉(zhuǎn)換結(jié)果。具體分配如下: 因?yàn)镸S5803的地址位僅有1位是可以設(shè)定的,所以一條I2C總線最多只能掛2個(gè)MS5803模塊。為了讓程序具有較好的可移植性,我們?cè)诒銓?xiě)程序時(shí)不使用對(duì)硬件的直接操作,而采用函數(shù)指針來(lái)操作,所以我們定義了:
/*向MS5803下發(fā)指令,指令格式均為1個(gè)字節(jié)*/ typedef void (*WriteCommandToMS5803Type)(uint8_t deviceAddress,uint8_t command); /*從MS5803讀取多個(gè)字節(jié)數(shù)據(jù)的值*/ typedef void (*ReadBytesFromMS5803Type)(uint8_t deviceAddress,uint8_t *pData,uint16_t bytesNum); 以上兩個(gè)函數(shù)指針來(lái)實(shí)現(xiàn)針對(duì)硬件的讀寫(xiě)操作。接下來(lái)我們開(kāi)始編寫(xiě)代碼。 (1)復(fù)位操作 復(fù)位操作的數(shù)據(jù)流如下圖所示,只需要發(fā)送一條命令就可完成: [url=] [/url] /*復(fù)位MS5803操作*/ void ResetForMS5803(uint8_t deviceAddress,WriteCommandToMS5803Type WriteCommandToMS5803) { uint8_t command=COMMAND_RESET; /*下發(fā)復(fù)位命令*/ WriteCommandToMS5803(deviceAddress,command); } [url=] [/url] (2)讀取校準(zhǔn)值 校準(zhǔn)值是出廠時(shí)廠家校準(zhǔn)的各種系數(shù),每臺(tái)設(shè)備都有差異,是固定不變的,只需要一次讀取就可以了,共有6個(gè)系數(shù),均為16為整數(shù)。首先發(fā)送讀系數(shù)的命令,然后讀取就可以了,每次讀取1個(gè),分6次讀取。過(guò)程數(shù)據(jù)流如下圖所示: [url=] [/url] /*從MS5803的PROM中讀取校準(zhǔn)數(shù)據(jù)*/ void GetCalibrationData(uint8_t deviceAddress,uint16_t *caliPara,WriteCommandToMS5803Type WriteCommandToMS5803,ReadBytesFromMS5803Type ReadBytesFromMS5803) { /*C1壓力靈敏度*/ caliPara[0]=ReadPromFromMS5803(deviceAddress,COMMAND_PROM_READ_C1,WriteCommandToMS5803,ReadBytesFromMS5803); /*C2壓力補(bǔ)償值*/ caliPara[1]=ReadPromFromMS5803(deviceAddress,COMMAND_PROM_READ_C2,WriteCommandToMS5803,ReadBytesFromMS5803); /*C3壓力靈敏度溫度系數(shù)*/ caliPara[2]=ReadPromFromMS5803(deviceAddress,COMMAND_PROM_READ_C3,WriteCommandToMS5803,ReadBytesFromMS5803); /*C4壓力補(bǔ)償溫度系數(shù)*/ caliPara[3]=ReadPromFromMS5803(deviceAddress,COMMAND_PROM_READ_C4,WriteCommandToMS5803,ReadBytesFromMS5803); /*C5參考溫度*/ caliPara[4]=ReadPromFromMS5803(deviceAddress,COMMAND_PROM_READ_C5,WriteCommandToMS5803,ReadBytesFromMS5803); /*C6溫度傳感器溫度系數(shù)*/ caliPara[5]=ReadPromFromMS5803(deviceAddress,COMMAND_PROM_READ_C6,WriteCommandToMS5803,ReadBytesFromMS5803); } [url=] [/url] (3)讀取轉(zhuǎn)換值 讀取轉(zhuǎn)換結(jié)果值是我們的目的,可以讀取溫度和壓力兩個(gè)量,不過(guò)一次只能讀一個(gè)。首先發(fā)送命令設(shè)定采集壓力還是溫度,并設(shè)定精度。然后發(fā)送讀取的命令,最后讀取對(duì)應(yīng)的值。再使用校準(zhǔn)系數(shù)計(jì)算出最終的物理值。  - /*獲取轉(zhuǎn)換值,包括溫度和壓力*/
-
- void GetConversionValue(uint8_t deviceAddress,float *pPres,float *pTemp,uint16_t *caliPara,uint16_t *semaphore,WriteCommandToMS5803Type WriteCommandToMS5803,ReadBytesFromMS5803Type ReadBytesFromMS5803)
-
- {
-
- uint16_t senst1; //C1壓力靈敏度
-
- uint16_t offt1; //C2壓力補(bǔ)償值
-
- uint16_t tcs; //C3壓力靈敏度溫度系數(shù)
-
- uint16_t tco; //C4壓力補(bǔ)償溫度系數(shù)
-
- uint16_t tref; //C5參考溫度
-
- uint16_t tempsens; //C6溫度傳感器溫度系數(shù)
-
-
-
- /*從MS5803的PROM中讀取校準(zhǔn)數(shù)據(jù)*/
-
- if(*semaphore>0)
-
- {
-
- GetCalibrationData(deviceAddress,caliPara,WriteCommandToMS5803,ReadBytesFromMS5803);
-
- *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;
-
-
- /*讀取壓力數(shù)據(jù)*/
-
- digitalPressureValue=ReadConversionFromMS5803(deviceAddress,COMMAND_CONVERTD1OSR4096,WriteCommandToMS5803,ReadBytesFromMS5803);
-
- Delayms(20);
-
-
- /*讀取溫度數(shù)據(jù)*/
-
- digitalTemperatureValue=ReadConversionFromMS5803(deviceAddress,COMMAND_CONVERTD2OSR4096,WriteCommandToMS5803,ReadBytesFromMS5803);
-
-
- /*對(duì)溫度進(jìn)行一階修正*/
-
- int32_t dT;
-
- int32_t temp;
-
- dT=digitalTemperatureValue-tref*256;
-
- temp=(int32_t)(2000+dT*tempsens/pow(2,23));
-
-
-
- /*對(duì)壓力進(jìn)行一階修正*/
-
- 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));
-
-
- /*對(duì)溫度和壓力進(jìn)行二階修正*/
-
- 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<=190000))
-
- {
-
- *pPres=(float)pres/100.0;
-
- }
-
- }
復(fù)制代碼
|