1. 程式人生 > 實用技巧 >外設驅動庫開發筆記11:SHT3x系列溫溼度感測器驅動

外設驅動庫開發筆記11:SHT3x系列溫溼度感測器驅動

  在我們的產品中經常會遇到溫溼度檢測的需求。可以用於檢測溫溼度的感測器元件也有很多。我們經常使用的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分別表示原始感測器輸出的溼度和溫度。只有當SRHST用十進位制表示時,這些公式才能正確工作。

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模擬的軟體收發控制都需要單獨做相應的配置。

歡迎關注: