環(huán)境傳感器是一類我們很常用的傳感器。它可以方便我們獲取壓力、溫度、濕度以及空氣質(zhì)量等數(shù)據(jù)。在這一篇中,我們將分析BME680環(huán)境傳感器的功能,并設(shè)計(jì)和實(shí)現(xiàn)BME680環(huán)境傳感器的驅(qū)動(dòng)。
1 、功能概述
BME680是一款專為移動(dòng)應(yīng)用和可穿戴設(shè)備開發(fā)的集成環(huán)境傳感器,其尺寸和低功耗是關(guān)鍵要求。
1.1 、硬件接口
BME680由一個(gè)8針金屬蓋3.0 x 3.0 x0.93mm3LGA封裝組成,旨在根據(jù)特定的工作模式,長(zhǎng)期穩(wěn)定性和高EMC穩(wěn)健性進(jìn)行優(yōu)化消耗??梢赃x擇采用I2C接口或者SPI接口。其管腳排布如下圖:
BME680環(huán)境傳感器可以選擇使用I2C接口或者SPI接口,在不同的接口模式及下各個(gè)引腳的定義及功能有一些差別。其具體分配及定義如下所示:
從上表中我們可以知道當(dāng)CSB引腳接高電平VDDIO時(shí),采用的是I2C接口。此時(shí)I2C的設(shè)備地址的最后一位由SDO引腳的電平?jīng)Q定。所以設(shè)備地址計(jì)7位為0x76或0x77,計(jì)8位則是0xEC或0xEE。
當(dāng)CSB引腳用作片選信號(hào)時(shí),則使用SPI接口。SPI接口支持模式0(CPOL=0,CPHA=0)和模式3(CPOL=1,CPHA=1)。同時(shí)支持3線SPI和4線SPI??刂谱止?jié)的最高位為0時(shí)表示寫,為1時(shí)表示讀。
1.2 、內(nèi)置傳感器
BME680擴(kuò)展了博世現(xiàn)有的環(huán)境傳感器系列,首次集成了高線性度和高精度的氣體,壓力,濕度和溫度傳感器。
1.2.1 、氣體傳感器
BME680內(nèi)的氣體傳感器可以檢測(cè)各種氣體,以測(cè)量個(gè)人健康的空氣質(zhì)量。BME680可檢測(cè)到的氣體包括油漆(如甲醛),油漆,脫漆劑,清潔用品,家具等的揮發(fā)性有機(jī)化合物(VOC)。大氣質(zhì)量傳感器的特性參數(shù)如下:
BME680采用了博世軟件環(huán)境群組解決方案。該解決方案使用智能算術(shù)方法將空氣質(zhì)量索引(IAQ)作為輸出。該指標(biāo)將IAQ劃分為0到500的索引數(shù)值用以指示IAQ,具體劃分如下所示:
1.2.2 、濕度傳感器
BME680集成了濕度傳感器用于外部環(huán)境中濕度數(shù)據(jù)的采集。濕度傳感器的性能參數(shù)如下:
1.2.3 、壓力傳感器
BME680集成有大氣壓力傳感器用于檢測(cè)外部環(huán)境的絕對(duì)壓力。壓力傳感器的性能參數(shù)如下:
1.2.4 、溫度傳感器
BME680也集成了溫度傳感器用以檢測(cè)溫度數(shù)據(jù),溫度數(shù)據(jù)除了指示環(huán)境溫度外,同時(shí)用于壓力和濕度的補(bǔ)償計(jì)算。溫度傳感器的性能參數(shù)如下:
1.3 、數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)
BME680采用特定的存儲(chǔ)器區(qū)域來存儲(chǔ)控制及數(shù)據(jù)信息。存儲(chǔ)的數(shù)據(jù)包括測(cè)量數(shù)據(jù)、控制信息以及校準(zhǔn)數(shù)據(jù)。
對(duì)于溫度傳感器,包括3個(gè)校準(zhǔn)參數(shù)和一個(gè)ADC測(cè)量數(shù)據(jù),其測(cè)量數(shù)據(jù)和校準(zhǔn)數(shù)據(jù)的存儲(chǔ)結(jié)構(gòu)及地址如下:
對(duì)于壓力傳感器,包括10個(gè)計(jì)算校準(zhǔn)數(shù)據(jù)和一個(gè)ADC轉(zhuǎn)換數(shù)據(jù),其測(cè)量數(shù)據(jù)的校準(zhǔn)數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)及地址如下:
對(duì)于濕度傳感器,包括7個(gè)計(jì)算校準(zhǔn)數(shù)據(jù)和一個(gè)ADC轉(zhuǎn)換數(shù)據(jù),其測(cè)量數(shù)據(jù)的校準(zhǔn)數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)及地址如下:
大氣質(zhì)量傳感器,包括3個(gè)計(jì)算校準(zhǔn)數(shù)據(jù)、一個(gè)加熱器范圍存儲(chǔ)數(shù)據(jù)、一個(gè)加熱器電阻校準(zhǔn)因子存儲(chǔ)數(shù)據(jù)、氣體ADC測(cè)量數(shù)據(jù)、氣體范圍數(shù)據(jù)以及范圍轉(zhuǎn)換錯(cuò)誤,其測(cè)量數(shù)據(jù)的校準(zhǔn)數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)及地址如下:
BME680環(huán)境傳感器寄存器都是8位的,所有的操作均通過對(duì)寄存器的讀寫來實(shí)現(xiàn)。全部控制寄存器及數(shù)據(jù)寄存器的結(jié)構(gòu)和地址如下:
這里我們需要說明一下,BME680的存儲(chǔ)器地址范圍是0x00~0xFF,在I2C接口通訊時(shí),通訊采用的是8位寄存器地址正好符合對(duì)應(yīng)的尋址范圍。但是采用SPI接口通訊時(shí),寄存器地址的最高為被用于區(qū)分讀寫操作,所以地址只有7位,存儲(chǔ)空間被分為2頁(yè)。具體如下:
所以在使用SPI接口時(shí)需要分辨是哪一頁(yè)。當(dāng)前操作的是哪一頁(yè)由Status寄存器來決定。
2 、驅(qū)動(dòng)設(shè)計(jì)與實(shí)現(xiàn)
我們對(duì)BME680環(huán)境傳感器的基本情況已經(jīng)有了整體了解,接下來我們將為BME680環(huán)境傳感器設(shè)計(jì)并實(shí)現(xiàn)驅(qū)動(dòng)程序。
2.1 、對(duì)象定義
我們依然是采用基于對(duì)象的操作。所以我們需要定義對(duì)象,所以我們需要抽象出對(duì)象類型,并對(duì)我們想要操作的對(duì)象進(jìn)行初始化。
2.1.1 、對(duì)象抽象
對(duì)于一個(gè)對(duì)象來說,一般包括有屬性和操作兩方面的內(nèi)容。接下來我們就從這兩個(gè)方面分析BME680環(huán)境傳感器的對(duì)象。
我們需要從BME680對(duì)象抽象出其屬性,這些屬性能夠定義一個(gè)對(duì)象的特點(diǎn)并將其與其它對(duì)象區(qū)別開來。BME680支持SPI通訊和I2C通訊,所以我們將通訊端口作為屬性以規(guī)定對(duì)象的通訊方式。在使用I2C時(shí),設(shè)備有地址以區(qū)別不同的設(shè)備,所以我們將I2C設(shè)備地址也定義為屬性。每臺(tái)BME680都有一個(gè)ID用以區(qū)別于其它設(shè)備,所以我們將它定義為對(duì)象的屬性。還有配置寄存器、測(cè)量控制寄存器、濕度控制寄存器、氣體控制寄存器都記錄了設(shè)備的配置狀態(tài),所以我們也將它們作為屬性。每臺(tái)設(shè)備都有特定的校準(zhǔn)數(shù)據(jù),這些校準(zhǔn)數(shù)據(jù)每次數(shù)據(jù)檢測(cè)都是需要的,所以我們用屬性將它們記錄下來。還有測(cè)量數(shù)據(jù),它們標(biāo)識(shí)了設(shè)備當(dāng)前的工作狀態(tài),所以我們將它們也作為屬性。
接下來我們分析BME680的操作。首先來講,我們肯定要與BME680交互,但我們對(duì)BME680的讀寫依賴于具體的硬件平臺(tái),所以我們將它們作為對(duì)象的操作。在進(jìn)行相關(guān)操作時(shí),我們需要控制時(shí)序,則需要使用延時(shí)操作,但延時(shí)處理總是依賴于具體的軟硬件平臺(tái),所以我們將延時(shí)處理作為對(duì)象的操作。而使用SPI時(shí),沒有設(shè)備地址但有片選信號(hào),如何操作片選信號(hào)依賴于硬件平臺(tái),我們將對(duì)片選的操作定義為對(duì)象的操作函數(shù)。
根據(jù)上述的分析,我們可以得到BME680環(huán)境傳感器的對(duì)象類型如下:
1 /*定義BME680操作對(duì)象*/
2 typedef struct BME680Object{
3 uint8_t chipID; //芯片ID
4 uint8_t bmeAddress; //I2C通訊時(shí)的設(shè)備地址
5 uint8_t memeryPage; //用于在SPI接口時(shí)記錄當(dāng)前所處的內(nèi)存頁(yè)
6 uint8_t config; //配置寄存器
7 uint8_t ctrlMeas; //測(cè)量控制寄存器
8 uint8_t ctrlHumi; //濕度測(cè)量控制寄存器
9 uint8_t ctrlGas0; //氣體控制寄存器0
10 uint8_t ctrlGas1; //氣體控制寄存器1
11 uint8_t resHeat;
12 uint8_t gasWait;
13
14 BME680PortType port; //接口選擇
15 BME680CalibParamType caliPara; //校準(zhǔn)參數(shù)
16
17 #if BME680_COMPENSATION_SELECTED > (0)
18 int32_t temperature; //溫度值
19 int32_t pressure; //壓力值
20 int32_t humidity; //濕度值
21 int32_t gasResistence; //大氣質(zhì)量電阻值
22 int32_t iaq; //空氣質(zhì)量水平
23 #else
24 float temperature; //溫度值
25 float pressure; //壓力值
26 float humidity; //濕度值
27 float gasResistence; //大氣質(zhì)量電阻值
28 float iaq; //空氣質(zhì)量水平
29 #endif
30
31 void (*Read)(struct BME680Object *bme,uint8_t regAddress,uint8_t *rData,uint16_t rSize); //讀數(shù)據(jù)操作指針
32 void (*Write)(struct BME680Object *bme,uint8_t regAddress,uint8_t command); //謝數(shù)據(jù)操作指針
33 void (*Delayms)(volatile uint32_t nTime); //延時(shí)操作指針
34 void (*ChipSelect)(BME680CSType cs); //使用SPI接口時(shí),片選操作
35 }BME680ObjectType;
片選操作有一點(diǎn)需要注意,如果片選信號(hào)在硬件電路上固定有效時(shí),可以將NULL給它,同樣在SPI接口時(shí)也需要將NULL給它。
2.1.2 、對(duì)象初始化函數(shù)
一個(gè)對(duì)象必須對(duì)其進(jìn)行初始化才可使用。初始化對(duì)象主要有四個(gè)方面的內(nèi)容:檢查對(duì)象賦值的合法性;屬性賦初值;為對(duì)象操作指定函數(shù)指針;對(duì)象所指向設(shè)備的初始配置。據(jù)此我們可以編寫B(tài)ME680環(huán)境傳感器的初始化函數(shù)如下:
1 /*實(shí)現(xiàn)BME680初始化配置*/
2 void BME680Initialization(BME680ObjectType *bme, //BMP280對(duì)象
3 uint8_t bmeAddress, //I2C接口是設(shè)備地址
4 BME680PortType port, //接口選擇
5 BME680IIRFilterType filter, //過濾器
6 BME680SPI3wUseType spi3W_en, //3線SPI控制
7 BME680TempSampleType osrs_t, //溫度精度
8 BME680PresSampleType osrs_p, //壓力精度
9 BME680SPI3wIntType spi3wint_en,//3線SPI中斷控制
10 BME680HumiSampleType osrs_h, //濕度精度
11 BME680GasRunType run_gas, //氣體運(yùn)行設(shè)置
12 BME680HeaterSPType nb_conv, //加熱器設(shè)定點(diǎn)選擇
13 BME680HeaterOffType heat_off, //加熱器關(guān)閉
14 uint16_t duration, //TPHG測(cè)量循環(huán)周期,ms單位
15 uint8_t tempTarget, //加熱器的目標(biāo)溫度
16 BME680Read Read, //讀數(shù)據(jù)操作指針
17 BME680Write Write, //寫數(shù)據(jù)操作指針
18 BME680Delayms Delayms, //延時(shí)操作指針
19 BME680ChipSelect ChipSelect //片選操作指針
20 )
21 {
22 uint8_t try_count = 5;
23 uint8_t regValue=0;
24
25 if((bme==NULL)||(Read==NULL)||(Write==NULL)||(Delayms==NULL))
26 {
27 return;
28 }
29 bme->Read=Read;
30 bme->Write=Write;
31 bme->Delayms=Delayms;
32
33 bme->port=port;
34 if(bme->port==BME680_I2C)
35 {
36 if((bmeAddress==0xEC)||(bmeAddress==0xEE))
37 {
38 bme->bmeAddress=bmeAddress;
39 }
40 else if((bmeAddress==0x76)||(bmeAddress==0x77))
41 {
42 bme->bmeAddress=(bmeAddress<<1);
43 }
44 else
45 {
46 return;
47 }
48 bme->ChipSelect=NULL;
49 }
50 else
51 {
52 if(ChipSelect!=NULL)
53 {
54 bme->ChipSelect=ChipSelect;
55 }
56 else
57 {
58 bme->ChipSelect=BME680ChipSelectDefault;
59 }
60 }
61
62 bme->chipID=0x00;
63 bme->pressure=0.0;
64 bme->temperature=25.0;
65 bme->humidity=0.0;
66 bme->bmeAddress=0x00;
67 bme->caliPara.t_fine=0;
68
69 if(!ObjectIsValid(bme))
70 {
71 return;
72 }
73
74 while(try_count--)
75 {
76 ReadBME680Register(bme,REG_BME680_ID,®Value,1);
77 bme->chipID=regValue;
78 if(0x61==bme->chipID)
79 {
80 BME680SoftReset(bme);
81
82 break;
83 }
84 }
85
86 if(try_count)
87 {
88 uint8_t waitTime;
89 waitTime=CalcProfileDuration(bme,duration,osrs_t,osrs_p,osrs_h);
90
91 //控制寄存器配置
92 ConfigControlRegister(bme,filter,spi3W_en,osrs_t,osrs_p,spi3wint_en,osrs_h,run_gas,nb_conv,heat_off,waitTime,tempTarget);
93
94 //讀取校準(zhǔn)值
95 GetBME680CalibrationData(bme);
96 }
97 }
2.2 、對(duì)象操作
每一個(gè)對(duì)象都有操作,我們使用對(duì)象的目的當(dāng)然是通過操作對(duì)象來獲取我們需要的數(shù)據(jù)。所以開發(fā)驅(qū)動(dòng)時(shí),對(duì)象的操作才是我們主要的工作內(nèi)容。在這里對(duì)BME680的操作就是對(duì)其寄存器的操作。
2.2.1 、寫寄存器操作
我們已經(jīng)說過了,對(duì)BME680的操作都是通過讀寫寄存器實(shí)現(xiàn)的。這里我們先來看寫寄存器。在I2C接口方式下,寫寄存器操作是在從站地址的最后一位來識(shí)別的,再加上要寫的寄存器地址和數(shù)據(jù)來實(shí)現(xiàn)的,這也是I2C協(xié)議的標(biāo)準(zhǔn)做法。其時(shí)序圖如下所示:
而在SPI接口方式下,由于SPI并未有設(shè)備地址,也不存在用從還在那地址最后為來標(biāo)記讀寫的模式。通常一些設(shè)備需要定義操作碼來實(shí)現(xiàn)讀寫區(qū)分,但BME680采取了將寄存器地址的最高位置零表示為寫。之所以可以這樣定義,是因?yàn)锽ME680寄存器地址分配的特殊性決定的。改變寄存器地址的最高位也能區(qū)分不同的寄存器,絕不會(huì)重復(fù)。在SPI接口方式下,寫寄存器的時(shí)序圖如下所示:
根據(jù)上述描述和時(shí)序圖,我們可以實(shí)現(xiàn)寫B(tài)ME680環(huán)境傳感器寄存器的程序。
1 /* 向BME680寄存器寫一個(gè)字節(jié) */
2 static void WriteBME680Register(BME680ObjectType *bme,uint8_t regAddress,uint8_t command)
3 {
4 if(ObjectIsValid(bme))
5 {
6 if(bme->port==BME680_SPI)
7 {
8 bme->ChipSelect(BME680CS_Enable);
9 bme->Delayms(1);
10 SetMemeryPageNumber(bme,regAddress);
11 regAddress&=0x7F;
12 bme->Delayms(1);
13 bme->Write(bme,regAddress,command);
14 bme->Delayms(1);
15 bme->ChipSelect(BME680CS_Disable);
16 }
17 else
18 {
19 bme->Write(bme,regAddress,command);
20 }
21 }
22 }
2.2.2 、讀寄存器操作
讀寄存器的處理方式與寫寄存器是類似。在I2C接口方式下,將從站地址的最低位置1來表示讀。在I2C接口方式下,讀寄存器的時(shí)序圖如下所示:
而在SPI接口方式下,通過將寄存器地址的最改為置1來標(biāo)識(shí)為讀操作。事實(shí)上,所有寄存器地址的最高為都是1,所以在讀操作時(shí)實(shí)際不需要做處理。在SPI接口方式下,讀寄存器的時(shí)序圖如下所示:
根據(jù)上述描述和時(shí)序圖,我們可以實(shí)現(xiàn)讀BME680環(huán)境傳感器寄存器的程序。
1 /*從BME680寄存器讀取數(shù)據(jù)*/
2 static uint8_t ReadBME680Register(BME680ObjectType *bme,uint8_t regAddress,uint8_t *rDatas,uint16_t rSize)
3 {
4 uint8_t bmeError=0xFF;
5
6 if(ObjectIsValid(bme))
7 {
8 if(bme->port==BME680_SPI)
9 {
10 bme->ChipSelect(BME680CS_Enable);
11 bme->Delayms(1);
12 SetMemeryPageNumber(bme,regAddress);
13 regAddress |= 0x80;
14 bme->Delayms(1);
15 bme->Read(bme,regAddress,rDatas,rSize);
16 bme->Delayms(1);
17 bme->ChipSelect(BME680CS_Disable);
18 }
19 else
20 {
21 bme->Read(bme,regAddress,rDatas,rSize);
22 }
23
24 bmeError=0x00;
25 }
26
27 return bmeError;
28 }
3 、驅(qū)動(dòng)的使用
上一節(jié)我們?cè)O(shè)計(jì)并實(shí)現(xiàn)了BME680環(huán)境傳感器的驅(qū)動(dòng)程序,但這個(gè)驅(qū)動(dòng)設(shè)計(jì)的是否合理還不確定,所以我們來設(shè)計(jì)一個(gè)簡(jiǎn)單的應(yīng)用驗(yàn)證BME680環(huán)境傳感器的驅(qū)動(dòng)。
3.1 、聲明并初始化對(duì)象
使用基于對(duì)象的操作我們需要先得到這個(gè)對(duì)象,所以我們先要使用前面定義的BME680環(huán)境傳感器對(duì)象類型聲明一個(gè)BME680環(huán)境傳感器對(duì)象變量,具體操作格式如下:
BME680ObjectType bme680;
聲明了這個(gè)對(duì)象變量并不能立即使用,我們還需要使用驅(qū)動(dòng)中定義的初始化函數(shù)對(duì)這個(gè)變量進(jìn)行初始化。這個(gè)初始化函數(shù)所需要的輸入?yún)?shù)如下:
BME680ObjectType *bme,BMP680對(duì)象
uint8_t bmeAddress,I2C接口是設(shè)備地址
BME680PortType port,接口選擇
BME680IIRFilterType filter,過濾器
BME680SPI3wUseType spi3W_en,3線SPI控制
BME680TempSampleType osrs_t,溫度精度
BME680PresSampleType osrs_p,壓力精度
BME680SPI3wIntType spi3wint_en,3線SPI中斷控制
BME680HumiSampleType osrs_h,濕度精度
BME680GasRunType run_gas,氣體運(yùn)行設(shè)置
BME680HeaterSPType nb_conv,加熱器設(shè)定點(diǎn)選擇
BME680HeaterOffType heat_off,加熱器關(guān)閉
uint16_t duration,TPHG測(cè)量循環(huán)周期,ms單位
uint8_t tempTarget,加熱器的目標(biāo)溫度
BME680Read Read,讀數(shù)據(jù)操作指針
BME680Write Write,寫數(shù)據(jù)操作指針
BME680Delayms Delayms,延時(shí)操作指針
BME680ChipSelect ChipSelect,片選操作指針
對(duì)于這些參數(shù),對(duì)象變量我們已經(jīng)定義了。其他的參數(shù)基本都是配置參數(shù),我們根據(jù)實(shí)際使用需求選擇輸入就好了。主要的是我們需要定義幾個(gè)函數(shù),并將函數(shù)指針作為參數(shù)。這幾個(gè)函數(shù)的類型如下:
1 /* 定義讀數(shù)據(jù)操作函數(shù)指針類型 */
2 typedef void (*BME680Read)(struct BME680Object *bme,uint8_t regAddress,uint8_t *rData,uint16_t rSize);
3 /* 定義寫數(shù)據(jù)操作函數(shù)指針類型 */
4 typedef void (*BME680Write)(struct BME680Object *bme,uint8_t regAddress,uint8_t command);
5 /* 定義延時(shí)操作函數(shù)指針類型 */
6 typedef void (*BME680Delayms)(volatile uint32_t nTime);
7 /* 定義使用SPI接口時(shí),片選操作函數(shù)指針類型 */
8 typedef void (*BME680ChipSelect)(BME680CSType cs);
對(duì)于這幾個(gè)函數(shù)我們根據(jù)樣式定義就可以了,具體的操作可能與使用的硬件平臺(tái)有關(guān)系。若采用的SPI接口則需注意片選操作,片選操作函數(shù)用于多設(shè)備需要軟件操作時(shí),如采用硬件片選可以傳入NULL即可。同樣如果采用的是I2C接口,則片選可以傳入NULL即可。具體函數(shù)定義如下:
1 /*讀BME680寄存器值*/
2 static void ReadDataFromBME680(BME680ObjectType *bme680,uint8_t regAddress,uint8_t *rData,uint16_t rSize)
3 {
4 HAL_I2C_Master_Transmit(&bme680hi2c, bme680->bmeAddress,®Address,1,1000);
5
6 HAL_I2C_Master_Receive(&bme680hi2c, bme680->bmeAddress+1,rData, rSize, 1000);
7 }
8
9 /*寫B(tài)ME680寄存器值*/
10 static void WriteDataToBME680(BME680ObjectType *bme680,uint8_t regAddress,uint8_t command)
11 {
12 uint8_t pData[2];
13
14 pData[0]=regAddress;
15 pData[1]=command;
16
17 HAL_I2C_Master_Transmit(&bme680hi2c,bme680->bmeAddress, pData, 2,1000);
18 }
對(duì)于延時(shí)函數(shù)我們可以采用各種方法實(shí)現(xiàn)。我們采用的STM32平臺(tái)和HAL庫(kù)則可以直接使用HAL_Delay()函數(shù)。于是我們可以調(diào)用初始化函數(shù)如下:
1 BME680Initialization(&bme680, //BME280對(duì)象
2 0xEC, //I2C接口是設(shè)備地址
3 BME680_I2C, //接口選擇
4 BME680_IIR_FILTER_COEFF_X127, //過濾器
5 BME680_SPI3W_DISABLE, //3線SPI控制
6 BME680_TEMP_SAMPLE_X16, //溫度精度
7 BME680_PRES_SAMPLE_X16, //壓力精度
8 BME680_SPI3W_INT_DISABLE, ///3線SPI中斷使能
9 BME680_HUMI_SAMPLE_X16, //濕度精度
10 BME680_GAS_RUN_ENABLE,//氣體運(yùn)行設(shè)置
11 BME680_HEATER_SP0,//加熱器設(shè)定點(diǎn)選擇
12 BME680_HEATER_DISABLE,//加熱器關(guān)閉
13 20,//TPHG測(cè)量循環(huán)周期,ms單位
14 200,//加熱器的目標(biāo)溫度
15 ReadDataFromBME680, //讀數(shù)據(jù)操作指針
16 WriteDataToBME680, //寫數(shù)據(jù)操作指針
17 HAL_Delay, //延時(shí)操作指針
18 NULL //片選操作指針
19 );
3.2 、基于對(duì)象進(jìn)行操作
我們定義了對(duì)象變量并使用初始化函數(shù)給其作了初始化。接著我們就來考慮操作這一對(duì)象獲取我們想要的數(shù)據(jù)。我們?cè)隍?qū)動(dòng)中已經(jīng)將獲取數(shù)據(jù)并轉(zhuǎn)換為轉(zhuǎn)換值的比例值,接下來我們使用這一驅(qū)動(dòng)開發(fā)我們的應(yīng)用實(shí)例。
1 /*獲取環(huán)境數(shù)據(jù)*/
2 void BME680GetEnvironmentalData(void)
3 {
4 float pressure; //壓力值
5 float temperature; //溫度值
6 float humidity; //濕度值
7 float gasResistance; //氣體電阻
8
9 GetBME680Measure(&bme680);
10
11 pressure=bme680.pressure;
12 temperature=bme680.temperature;
13 humidity=bme680.humidity;
14 gasResistance=bme680.gasResistence;
15 }
4 、應(yīng)用總結(jié)
我們?cè)O(shè)計(jì)并實(shí)現(xiàn)了BME680環(huán)境傳感器的驅(qū)動(dòng)程序,并基于這一驅(qū)動(dòng)程序設(shè)計(jì)了簡(jiǎn)單的應(yīng)用。我們獲得了BME680檢測(cè)的全部環(huán)境數(shù)據(jù),結(jié)果也是令我們滿意的,這說明我們的驅(qū)動(dòng)設(shè)計(jì)是正確的。
在使用驅(qū)動(dòng)時(shí)需注意,采用SPI接口的器件需要考慮片選操作的問題。如果片選信號(hào)是通過硬件電路來實(shí)現(xiàn)的,我們?cè)诔跏蓟瘯r(shí)給其傳遞NULL值。如果是軟件操作片選則傳遞我們編寫的片選操作函數(shù)。而如果采用I2C接口,那么在初始化時(shí)也應(yīng)傳遞NULL值。
BME680環(huán)境傳感器支持SPI和I2C兩種接口,而且SPI也支持3線和4線模式,但我們?cè)跍y(cè)試應(yīng)用中只使用了I2C接口,SPI接口還有待測(cè)試。BME680環(huán)境傳感器在使用SPI接口時(shí),支持SPI模式0(CPOL=CPHA=0)和模式3(CPOL=CPHA=1)。而在使用I2C接口時(shí),支持標(biāo)準(zhǔn)模式、快速模式以及高速模式。而且在使用I2C接口時(shí),SDO引腳必須接高電平或低電平,以確定設(shè)備地址。
BME680環(huán)境傳感器有2種工作模式:休眠模式和強(qiáng)制模式。在設(shè)備上電后就進(jìn)入休眠模式,在這種模式下設(shè)備不執(zhí)行測(cè)量工作。一旦啟動(dòng)強(qiáng)制模式則執(zhí)行一遍TPHG循環(huán)檢測(cè)。模式設(shè)定的具體定義如下:
對(duì)于BME680環(huán)境傳感器有一個(gè)測(cè)量范圍寄存器,這個(gè)寄存器的值對(duì)應(yīng)兩組計(jì)算常數(shù),這下常數(shù)用于測(cè)量值的計(jì)算,具體如下:
總的來說對(duì)BME680環(huán)境傳感器的讀寫操作本身并不復(fù)雜,但其計(jì)算與修正關(guān)系卻相對(duì)復(fù)雜,特別是氣體質(zhì)量數(shù)據(jù)更應(yīng)注意。
源碼下載:https://github.com/foxclever/ExPeriphDriver
評(píng)論
查看更多