在我們的產品中經常會遇到溫濕度檢測的需求。可以用於檢測溫濕度的傳感器元件也有很多。我們經常使用的SHT各系列數字溫濕度傳感器來實現應用需求。在這里我們將設計並實現SHT3x系列溫濕度傳感器的驅動。
1、功能概述
SHT3x系列溫濕度傳感器是適用於各種應用的高品質濕度傳感器。SHT3x溫濕度傳感器系列結合了多種功能和各種接口適合各類應用。
1.1、硬件描述
SHT3x建立在全新和優化的CMOSens®芯片之上,進一步提高了產品可靠性和精度規格。SHT3x提供了一系列新功能,如增強信號處理、兩個獨特和用戶可選I2C地址、一個可編程溫濕度極限的報警模式,以及高達1 MHz的通信速度。SHT3x系列溫濕度傳感器的引腳排布及說明如下圖所示:
SHT3x系列溫濕度傳感器適用於2.15至5.5 V的寬電源電壓范圍。電源插腳必須與一個100nf電容解耦,該電容應盡可能靠近傳感器。
SCL和SDA線都是開放式I/O,帶有到VDD和VSS的二極管。它們應該連接到外部上拉電阻。I2C總線上的設備必須只驅動線路到地面。外部上拉電阻必須把信號高。上拉電阻可能包括在微控制器的I/O電路中。SHT3x系列溫濕度傳感器接線方式如下圖:
SCL用於同步微控制器與傳感器之間的通信。時鍾頻率可以自由選擇在0到1000千赫之間。支持根據I2C標准伸縮時鍾的命令。SDA引腳用於在傳感器之間傳輸數據。頻率高達400khz的通信必須滿足I2C快速模式標准。
1.2、信息通訊
SHT3x系列溫濕度傳感器支持I2C快速模式(頻率高達1000千赫)。可以通過適當的用戶命令啟用和禁用時鍾拉伸。
向傳感器發送一個命令后,傳感器需要最少等待1ms的時間才能接收到另一個命令。所有SHT3x命令和數據都映射到16位地址空間。此外,數據和命令由CRC校驗和保護。這增加了通信的可靠性。傳感器的16位命令已經包含一個3位CRC校驗和。傳感器發送和接收的數據總是由一個8位CRC來完成。在寫方向上,必須傳輸校驗和,因為SHT3x只接受后面跟着正確校驗和的數據。在讀取方向上,由主程序讀取和處理校驗和。
SHT3x系列溫濕度傳感器可以通過ADDR引腳設置設備的通訊地址。請注意,I2C地址是通過I2C讀寫頭的7個msb表示的,LSB在讀寫操作之間切換。具體的地址如下:
1.3、數據轉換
測量數據總是以16位無符號整數的形式傳輸。這些值已經線性化,並補償了溫度和電源電壓的影響。可以使用簡單的公式將這些原始值轉換為物理量值。相對濕度換算公式(結果為%RH):
溫度轉換公式(結果為攝氏度和華氏度):
SRH和ST分別表示原始傳感器輸出的濕度和溫度。只有當SRH和ST用十進制表示時,這些公式才能正確工作。
2、驅動設計與實現
我們已經了解了SHT3x系列溫濕度傳感器基本技術特性,接下來我們進一步考慮如何設計並實現SHT3x系列溫濕度傳感器的驅動。
2.1、對象定義
在使用一個對象之前我們需要獲得一個對象。同樣的我們想要SHT3x系列溫濕度傳感器就需要先定義SHT3x系列溫濕度傳感器的對象。
2.1.1、對象的抽象
我們要得到SHT3x系列溫濕度傳感器對象,需要先分析其基本特性。一般來說,一個對象至少包含兩方面的特性:屬性與操作。接下來我們就來從這兩個方面思考一下SHT3x系列溫濕度傳感器的對象。
先來考慮屬性,作為屬性肯定是用於標識或記錄對象特征的東西。我們來考慮SHT3x系列溫濕度傳感器對象屬性。作為一個I2C總線設備,設備地址用於標識設備在總線上的唯一性,所以我們將設備地址作為SHT3x對象的一個屬性。對於每一個SHT3x設備都有一個電子標識碼,它是標識SHT3x設備個體的東西,所以我們將其作為SHT3x對象的屬性。此外,溫濕度的當前值標識了當前的狀態我們將其作為兩個屬性。還有SHT3x的狀態寄存器也是記錄SHT3x配置及工作狀態的,所以我們也將其作為SHT3x對象的屬性。
接着我們還需要考慮SHT3x系列溫濕度傳感器對象的操作問題。作為數字通訊設備,我們向其發送數據和從其接收數據都是必要,但接收與發送數據依賴於所處的硬件平台,所以我們將發送數據與接收數據作為SHT3x對象的兩個操作。基於時序操作的需要,在通訊過程中需要作延時處理,但如何實現延時依賴於具體的硬件平台,所以我們也將延時處理作為SHT3x對象的一個操作。
根據上述我們對SHT3x溫濕度傳感器的分析,我們可以定義SHT3x溫濕度傳感器的對象類型如下:
1 /* 定義SHT3x對象類型 */ 2 typedef struct SHT3xObject{ 3 uint8_t devAddress; // SHT3x對象的地址 4 SHT3xStatusRegister status; // SHT3x狀態及存期的值 5 uint32_t serialNumber; // SHT3x對象的序列號 6 float temperature; 7 float humidity; 8 void (*Delayms)(volatile uint32_t nTime); //延時操作指針 9 void (*Receive)(uint8_t devAddress,uint8_t *rData,uint16_t rSize); //接收數據操作指針 10 void (*Transmit)(uint8_t devAddress,uint8_t *tData,uint16_t tSize); //發送數據操作指針 11 }SHT3xObjectType;
2.1.2、對象初始化
我們知道,一個對象僅作聲明是不能使用的,我們需要先對其進行初始化,所以這里我們來考慮SHT3x系列溫濕度傳感器對象的初始化函數。一般來說,初始化函數需要處理幾個方面的問題。一是檢查輸入參數是否合理;二是為對象的屬性賦初值;三是對對象作必要的初始化配置。這里我們就從這幾個方面入手設計SHT3x系列溫濕度傳感器對象的初始化函數。
1 /* SHT3x對象初始化 */ 2 SHT3xErrorType SHT3xInitialization(SHT3xObjectType *sht, 3 uint8_t address, 4 SHT3xTransmit transmit, 5 SHT3xReceive receive, 6 SHT3xDelayms delayms) 7 { 8 SHT3xErrorType error=SHT3X_NO_ERROR; 9 if((sht==NULL)||(transmit==NULL)||(receive==NULL)||(delayms==NULL)) 10 { 11 return SHT3X_PARM_ERROR; 12 } 13 14 sht->Transmit=transmit; 15 sht->Receive=receive; 16 sht->Delayms=delayms; 17 18 sht->temperature=0.0; 19 sht->humidity=0.0; 20 21 if((address==0x44)||(address==0x45)) 22 { 23 sht->devAddress=(address<<1); 24 } 25 else if((address==0x88)||(address==0x8A)) 26 { 27 sht->devAddress=address; 28 } 29 else 30 { 31 sht->devAddress=0; 32 error|=SHT3X_PARM_ERROR; 33 } 34 35 sht->status.word=0; 36 error|=SHT3xReadStatusRegister(sht); 37 38 if(error==SHT3X_NO_ERROR) 39 { 40 error|=SHT3xReadSerialNumber(sht); 41 } 42 43 return error; 44 }
2.2、對象操作
我們已經完成了SHT3x系列溫濕度傳感器對象類型的定義和對象初始化函數的設計。但我們的主要目標是獲取對象的信息,接下來我們還要實現面向SHT3x溫濕度傳感器的各類操作。
2.2.1、單次測量
SHT3X溫濕度傳感器有一種單次測量模式。這種模式只按我們規定的方式運行一次,測量通信序列由一個啟動條件、I2C寫標頭和一個16位測量命令組成。在傳感器完成測量后,通過發送一個START條件和一個I2C讀標頭,主控可以讀取測量結果。具體的格式如下:
根據這一單次數據測量並讀取的流程圖,我們可以很方便的得到單次讀取SHT3X溫濕度傳感器數據的程序。
1 /* 獲取一次性采集 */ 2 SHT3xErrorType SHT3xGetSingleShotData(SHT3xObjectType *sht,SHT3xRepeatability repeatability,SHT3xMode mode) 3 { 4 SHT3xErrorType error=SHT3X_NO_ERROR; 5 uint8_t data[6]; 6 uint16_t tempCode; 7 uint16_t humiCode; 8 9 SHT3xCommands commands[2][3]={{CMD_MEAS_CLOCKSTR_H, // 單次數據采集模式,時鍾延展,高重復性 10 CMD_MEAS_CLOCKSTR_M, // 單次數據采集模式,時鍾延展,中重復性 11 CMD_MEAS_CLOCKSTR_L, // 單次數據采集模式,時鍾延展,低重復性 12 }, 13 {CMD_MEAS_POLLING_H, // 單次數據采集模式,輪詢,高重復性 14 CMD_MEAS_POLLING_M, // 單次數據采集模式,輪詢,中重復性 15 CMD_MEAS_POLLING_L, // 單次數據采集模式,輪詢,低重復性 16 }}; 17 18 SHT3xWriteCommand(sht,commands[mode][repeatability]); 19 20 if(mode==MODE_CLKSTRETCH) 21 { 22 sht->Delayms(1); 23 } 24 else if(mode==MODE_POLLING) 25 { 26 sht->Delayms(20); 27 } 28 29 sht->Receive(sht,data,6); 30 31 error|=CheckCRC8ForSHT3x(&data[0],2,data[2]); 32 33 error|=CheckCRC8ForSHT3x(&data[3],2,data[5]); 34 35 if(error==SHT3X_NO_ERROR) 36 { 37 tempCode=(data[0]<<8)+data[1]; 38 humiCode=(data[3]<<8)+data[4]; 39 40 sht->temperature=CalcTemperatureValue(tempCode); 41 sht->humidity=CalcHumidityValue(humiCode); 42 } 43 44 return error; 45 }
2.2.2、周期測量
SHT3X溫濕度傳感器還有一種周期性檢測數據的方式。這種方式先將SHT3X溫濕度傳感器配置為周期獲取模式。在這一模式下就可以周期獲取數據了。周期獲取數據的格式如下圖:
根據上述周期讀取數據的字節順序圖我們可以編寫周期獲取的程序如下:
1 /* 讀取周期性采集的數據 */ 2 SHT3xErrorType SHT3xFetchPeriodicMeasurmentData(SHT3xObjectType *sht) 3 { 4 SHT3xErrorType error=SHT3X_NO_ERROR; 5 uint8_t data[6]; 6 uint16_t tempCode; 7 uint16_t humiCode; 8 9 SHT3xWriteCommand(sht,CMD_FETCH_DATA); 10 11 sht->Delayms(1); 12 13 sht->Receive(sht,data,6); 14 15 error|=CheckCRC8ForSHT3x(&data[0],2,data[2]); 16 17 error|=CheckCRC8ForSHT3x(&data[3],2,data[5]); 18 19 if(error==SHT3X_NO_ERROR) 20 { 21 tempCode=(data[0]<<8)+data[1]; 22 humiCode=(data[3]<<8)+data[4]; 23 24 sht->temperature=CalcTemperatureValue(tempCode); 25 sht->humidity=CalcHumidityValue(humiCode); 26 } 27 28 return error; 29 }
2.2.3、系統復位
對於SHT3X來說系統復位包括的內容比較多,有接口復位、軟件復位、廣播復位和硬件復位引腳復位。這里我們需要考慮的主要是軟件復位,其操作方式如下圖:
根據上圖我們可以很輕松的實現軟件復位操作。
2.2.4、內部加熱器
SHT3x配備了內部加熱器,但僅用於可靠性檢查。加熱器可以通過命令開關,控溫范圍大約在幾度范圍之內。其狀態可在狀態寄存器中查看,默認加熱器是關閉。器操作命令如下:
但是不建議操作加熱器。
2.2.5、狀態寄存器
狀態寄存器包含有關加熱器運行狀態、警報模式以及最后一個命令的執行狀態和最后一個寫序列的信息。讀取狀態寄存器的命令如下所示:
狀態寄存器的第15、11、10、4位等是我們關系比較多的,這些報警標志位可以通過命令清楚。根據上述數據字節流圖我們可以得到讀狀態寄存器的函數如下:
1 /* 讀取狀態寄存器的值 */ 2 SHT3xErrorType SHT3xReadStatusRegister(SHT3xObjectType *sht,SHT3xStatusRegister *status) 3 { 4 SHT3xErrorType error=SHT3X_NO_ERROR; 5 uint8_t sta[3]; 6 7 SHT3xWriteCommand(sht,CMD_READ_STATUS); 8 9 sht->Delayms(1); 10 11 sht->Receive(sht,sta,3); 12 13 error|=CheckCRC8ForSHT3x(&sta[0],2,sta[2]); 14 15 if(error==SHT3X_NO_ERROR) 16 { 17 status->word=(sta[0]<<8)+sta[1]; 18 } 19 else 20 { 21 status->word=0; 22 } 23 24 return error; 25 }
3、驅動的使用
我們已經設計並實現了SHT3x溫濕度傳感器驅動,接下來我們還需要對這一驅動進行驗證,所以我們要基於此驅動設計一個簡單的應用。
3.1、聲明並初始化對象
使用基於對象的操作我們需要先得到這個對象,所以我們先要使用前面定義的SHT3X溫濕度傳感器對象類型聲明一個SHT3X溫濕度傳感器對象變量,具體操作格式如下:
SHT3xObjectType sht3x;
聲明了這個對象變量並不能立即使用,我們還需要使用驅動中定義的初始化函數對這個變量進行初始化。這個初始化函數有很多的輸入參數,要求如下:
SHT3xObjectType *sht,待初始化的SHT3X
uint8_t address,設備地址
SHT3xReceive receive,接收數據函數指針
SHT3xTransmit transmit,發送數據函數指針
SHT3xDelayms delayms,毫秒延時函數指針
對於這些參數,對象變量我們已經定義了。設備地址則根據實際的使用地址輸入即可。主要的是我們需要定義幾個函數,並將函數指針作為參數。這幾個函數的類型如下:
1 /* 毫秒延時函數指針類型 */ 2 typedef void (*SHT3xDelayms)(volatile uint32_t nTime); 3 4 /* 接收數據函數指針類型 */ 5 typedef void (*SHT3xReceive)(SHT3xObjectType *sht,uint8_t *rData,uint16_t rSize); 6 7 /* 發送數據函數指針類型 */ 8 typedef void (*SHT3xTransmit)(SHT3xObjectType *sht,uint8_t *tData,uint16_t tSize);
對於這幾個函數我們根據樣式定義就可以了,具體的操作可能與使用的硬件平台有關系。我們的應用基於STM32F4平台實現,接下來將基於我們的平台實現這些函數。具體函數定義如下:
1 /*從SHT3X接收數據*/ 2 static void ReceiveFromSHT3x(SHT3xObjectType *sht,uint8_t *rData,uint16_t rSize) 3 { 4 HAL_I2C_Master_Receive(&sht3xi2c, sht->devAddress,rData, rSize, 1000); 5 } 6 7 /*向SHT3X傳送數據*/ 8 static void TransmitToSHT3x(SHT3xObjectType *sht,uint8_t *tData,uint16_t tSize) 9 { 10 HAL_I2C_Master_Transmit(&sht3xi2c,sht->devAddress,tData,tSize,1000); 11 }
對於延時函數我們可以采用各種方法實現。我們采用的STM32平台和HAL庫則可以直接使用HAL_Delay()函數。於是我們可以調用初始化函數如下:
SHT3xInitialization(&sht3x,0x88,TransmitToSHT3x,ReceiveFromSHT3x,HAL_Delay);
其中0x88為設備地址。
3.2、基於對象進行操作
我們定義了對象變量並使用初始化函數給其作了初始化。接着我們就來考慮操作這一對象獲取我們想要的數據。我們在驅動中已經將獲取數據並轉換為轉換值的比例值,接下來我們使用這一驅動開發我們的應用實例。
1 /*獲取溫濕度計數據*/ 2 void SHT3xMeasureData(void) 3 { 4 float humidity; 5 float temperature; 6 7 SHT3xErrorType error=SHT3X_NO_ERROR; 8 9 SHT3xStatusRegister status; 10 11 error|=SHT3xReadStatusRegister(&sht3x,&status); 12 13 if(error!=SHT3X_NO_ERROR) 14 { 15 return ; 16 } 17 18 if(status.bit.ResetDetected) 19 { 20 SHT3xClearStatusRegister(&sht3x); 21 22 SHT3xStartPeriodicMeasurment(&sht3x,REPEATAB_HIGH,FREQUENCY_1HZ); 23 } 24 25 error|=SHT3xFetchPeriodicMeasurmentData(&sht3x); 26 27 if(error==SHT3X_NO_ERROR) 28 { 29 temperature=sht3x.temperature; 30 humidity=sht3x.humidity; 31 } 32 }
4、應用總結
我們已經設計並實現了SHT3x溫濕度傳感器的驅動程序,也使用這一驅動程序實現了讀取SHT3x溫濕度傳感器溫度、濕度數據的簡單應用。經我們測試所得到的結果是符合我們期望的,這也說明驅動程序的設計是成功的。
在使用驅動時還需注意,在做初始化配置時,對狀態寄存器的寫操作需注意不得變更預留位且相關的預留位的默認值以后可能會改變。因此,在進行任何寫用戶寄存器的操作之前,必須先讀預留位的默認值。而且在初始化配置時,還要注意SHT3X 中OTP功能默認為禁止狀態,且不推薦用戶使用。
因為SHT3x溫濕度傳感器采用的是標准I2C接口,所以在驅動設計中沒有考慮硬件接口相關的內容。我們只專注於SHT3x溫濕度傳感器的配置與操作。所以在使用驅動程序時,無論是使用硬件I2C收發控制器還是使用GPIO模擬的軟件收發控制都需要單獨做相應的配置。