溫濕度檢測是嵌入式編程中經常應用到的一項功能。在我們的產品中亦經常使用。SHT2x系列溫濕度傳感器作為一種高精度低成本的集成模塊,一直應用于我們的產品中。在這里我們討論如何封裝SHT2x系列溫濕度傳感器的驅動。
1 、功能概述
SHT20配有一個全新設計的CMOSens芯片、一個經過改進的電容式濕度傳感元件和一個標準的能隙溫度傳感元件,其性能已經大大提升甚至超出了前一代傳感器(SHT1x和SHT7x)的可靠性水平。
1.1 、硬件描述
SHT2x濕度和溫度傳感器采用了新的封裝模式和數字接口,每一個傳感器都經過校準和測試。在產品表面印有產品批號,同時在芯片內存儲了電子識別碼-可以通過輸入命令讀出這些識別碼。此外,SHT2x溫濕度傳感器的分辨率可以通過輸入命令進行改變(8/12bit乃至12/14bit的RH/T),傳感器可以檢測到電池低電量狀態,并且輸出校驗和,有助于提高通信的可靠性。SHT2x溫濕度傳感器的封裝及引腳定義如下圖:
SHT2x 溫濕度傳感器的供電范圍為 2.1-3.6V,推薦電壓為 3.0V。電源(VDD)和接地(VSS)之間須連接一個100nF的去耦電容,且電容的位置應盡可能靠近傳感器。數字接口為標準I2C總線。接線方式如下圖:
1.2 、串行通訊
SHT2x溫濕度傳感器采用標準的 I2C協議進行通訊。在啟動傳輸后,隨后傳輸的I2C首字節包括 7位的I2C設備地址(B-范例地址“1000’000”)和一個SDA方向位(讀 R:“1”,寫 W:“0”)。在第 8個SCL時鐘下降沿之后,通過拉低 SDA引腳(ACK位),指示傳感器數據接收正常。在發出測量命令之后(“1110’0011”代表溫度測量,“1110’0101”代表相對濕度測量),MCU必須等待測量完成?;镜拿盍斜砣缦拢?/p>
從上表我們知道,讀取SHT2x溫濕度傳感器數據有兩種不同的方式可選,主機模式或非主機模式。在主機模式下,在測量的過程中, SCL線被封鎖(由傳感器進行控制),在非主機模式下,當傳感器在執行測量任務時,SCL線仍然保持開放狀態,可進行其他通訊。非主機模式允許傳感器進行測量時在總線上處理其他 I2C總線通訊任務。
1.3 、數據轉換
傳感器內部設置的默認分辨率為相對濕度12位和溫度14位。SDA的輸出數據被轉換成兩個字節的數據包,高字節MSB在前(左對齊)。每個字節后面都跟隨一個應答位。兩個狀態位,即LSB的后兩位在進行物理計算前須置“0”。
不論基于哪種分辨率,相對濕度RH都可以根據SDA輸出的相對濕度信號 SRH通過如下公式計算獲得(結果以%RH表示)。
以上所給出的 RH物理值對應于世界氣象組織(WMO)所規定的基于液態水的相對濕度。基于冰的相對濕度RHi可通過特定溫度t下基于水的相對濕度 RHw轉換而來,同樣參照應用說明:
相對濕度單位為 %RH溫度單位為°C fortemperature. 相關系數如下:
不論基于哪種分辨率,溫度 T都可以通過將溫度輸出信號 ST代入到下面的公式計算得到(結果以溫度°C表示):
2 、驅動設計與實現
我們已經了解了SHT2x系列溫濕度傳感器基本技術特性,接下來我們進一步考慮如何設計并實現SHT2x系列溫濕度傳感器的驅動。
2.1 、對象定義
在使用一個對象之前我們需要獲得一個對象。同樣的我們想要SHT2x系列溫濕度傳感器就需要先定義SHT2x系列溫濕度傳感器的對象。
2.1.1 、對象的抽象
我們要得到SHT2x系列溫濕度傳感器對象,需要先分析其基本特性。一般來說,一個對象至少包含兩方面的特性:屬性與操作。接下來我們就來從這兩個方面思考一下SHT2x系列溫濕度傳感器的對象。
先來考慮屬性,作為屬性肯定是用于標識或記錄對象特征的東西。我們來考慮SHT2x系列溫濕度傳感器對象屬性。首先對于I2C設備會有一個地址,用于表示總線上不同的通訊節點,所以我們將設備地址作為SHT2x系列溫濕度傳感器對象的一個屬性。用戶寄存器標識了設備的配置狀態,所以我們也將其作為SHT2x系列溫濕度傳感器對象的一個屬性。同樣的每個SHT2X都有一個電子識別碼,用以標識SHT2X設備的身份,所以我們也將其作為SHT2x系列溫濕度傳感器對象的一個屬性。此外我們也將讀出來的溫濕度的數字編碼所以我們也將其作為SHT2x系列溫濕度傳感器對象的屬性以記錄當前狀態。
接著我們還需要考慮SHT2x系列溫濕度傳感器對象的操作問題。通過I2C總線發送數據或者接收數據均依賴于具體的操作平臺,所以我們將向SHT2x發送數據以及從SHT2x獲取數據均作為SHT2x系列溫濕度傳感器對象的操作。此外,在驅動中會用到延時操作函數,延時操作一般也會依賴于具體平臺的實現,所以我們也將其作為SHT2x系列溫濕度傳感器對象的操作。
根據上述我們對SHT2x溫濕度傳感器的分析,我們可以定義SHT2x溫濕度傳感器的對象類型如下:
/*定義SHT2x對象*/
typedef structSHT2xObject{
uint8_t userReg; //用戶寄存器
uint8_t devAddress; //設備地址
uint8_t sn[8]; //設備序列號
uint16_t tempCode; //溫度的數值碼
uint16_t humiCode; //濕度的數值碼
void (*Delayms)(volatile uint32_tnTime); //毫秒延時操作指針
void (*Transmit)(struct SHT2xObject *sht,uint8_t *tData,uint16_t tSize); //發送數據操作指針
void (*Receive)(struct SHT2xObject *sht,uint8_t *rData,uint16_t rSize); //接收數據操作指針
}SHT2xObjectType;
2.1.2 、對象初始化
我們知道,一個對象僅作聲明是不能使用的,我們需要先對其進行初始化,所以這里我們來考慮SHT2x系列溫濕度傳感器對象的初始化函數。一般來說,初始化函數需要處理幾個方面的問題。一是檢查輸入參數是否合理;二是為對象的屬性賦初值;三是對對象作必要的初始化配置。據此我們設計SHT2x系列溫濕度傳感器對象的初始化函數如下:
/* 初始化配置SHT2x */
void SHT2xInitialization(SHT2xObjectType*sht,
SHT2xDPIType dpi,
SHT2xBatteryType endBat,
SHT2xHeaterType heater,
SHT2xOTPType otp,
SHT2xTransmit write,
SHT2xReceive read,
SHT2xDelayms delayms)
{
uint8_t userReg=0;
uint8_t dpiSet[4]={DPI_RH12_T14,DPI_RH8_T13,DPI_RH10_T12,DPI_RH11_T11};
uint8_t batEnd[2]={END_OF_BATTERY_H,END_OF_BATTERY_L};
uint8_t heaterSet[2]={ONCHIPHEATERDISABLE,ONCHIPHEATERENABLE};
uint8_t otpSet[2]={OTPENABLE,OTPDISABLE};
if((sht==NULL)||(write==NULL)||(read==NULL)||(delayms==NULL))
{
return;
}
sht->Transmit=write;
sht->Receive=read;
sht->Delayms=delayms;
sht->devAddress=SHT2X_ADDRESS;
sht->tempCode=0;
sht->humiCode=0;
userReg=dpiSet[dpi]|batEnd[endBat]|heaterSet[heater]|otpSet[otp];
SetSHT2xUserRegister(sht,userReg); //配置用戶寄存器
sht->Delayms(20);
GetSHT2xUserRegister(sht); //讀取用戶寄存器
GetSHT2xSerialNumber(sht); //獲取電子識別碼
}
2.2 、對象操作
我們已經完成了SHT2x系列溫濕度傳感器對象類型的定義和對象初始化函數的設計。但我們的主要目標是獲取對象的信息,接下來我們還要實現面向SHT2x溫濕度傳感器的各類操作。
2.2.1 、軟件復位
軟件復位命令用于在無需關閉和再次打開電源的情況下,重新啟動傳感器系統。在接收到這個命令之后,傳感器系統開始重新初始化,并恢復默認設置狀態,用戶寄存器的加熱器位除外。軟復位所需時間不超過15毫秒。命令格式如下:
/*軟件復位*/
void SoftResetSHT2x(SHT2xObjectType*sht)
{
uint8_t tData=SOFT_RESET;
sht->Transmit(sht,&tData,1);
}
2.2.2 、用戶寄存器操作
用戶寄存器用于配置SHT2X的工作特性,包括測量分辨率、電池電壓、OTP加載和片內加熱器配置等。用戶寄存器的結構及各位的定義如下:
電池電量不足警報在電源電壓下降到 2.25V 以下時激活。內部加熱器用于傳感器功能性診斷,溫度升高時相對濕度降低。OTP重加載為一個安全功能,可以在每次測量前將整個OTP設置加載到寄存器,加熱器位除外。SHT2X中此功能默認為禁止狀態,且不推薦用戶使用。請采用軟復位代替它包含OTP重加載。
/*配置用戶寄存器*/
static voidSetSHT2xUserRegister(SHT2xObjectType *sht,uint8_t cmd)
{
uint8_t status;
uint8_t command;
uint8_t pData[2];
GetSHT2xUserRegister(sht);
status=sht->userReg&0x38;
command=cmd&0xC7;
command=command|status;
if(command!=sht->userReg)
{
pData[0]=WRITE_USER_REGISTER;
pData[1]=command;
sht->Transmit(sht,pData,2);
sht->Delayms(10);
GetSHT2xUserRegister(sht);
}
}
在配置用戶寄存器時,需注意不得變更預留位且相關的預留位的默認值以后可能會改變。因此,在進行任何寫寄存器的操作之前,必須先讀預留位的默認值。之后,用戶寄存器字節由對應的預留位的默認值和其他剩余位的默認值或者寫入值組成。
2.2.3 、數據獲取
SHT2x溫濕度傳感器數據獲取有主機模式或非主機模式兩種。我們在這里先看看非主機模式,在非主機模式下,MCU需要對傳感器狀態進行查詢。此過程通過發送一個啟動傳輸時序,之后緊接著是如下圖所示的I2C首字節(1000’0001)來完成。如果內部處理工作完成,單片機查詢到傳感器發出的確認信號后,相關數據就可以通過MCU進行讀取。如果測量處理工作沒有完成,傳感器無確認位(ACK)輸出,此時必須重新發送啟動傳輸時序。
根據上述描述和時序圖我們可以得到獲取數據的函數如下:
/*讀取SHT2x的濕度數據*/
floatGetSHT2xHumidityValue(SHT2xObjectType *sht,uint8_t cmd)
{
uint8_t data[3]={0,0,0};
uint16_t result=0;
/*設置轉換命令*/
sht->Transmit(sht,&cmd,1);
sht->Delayms(29);
/*讀取數據*/
sht->Receive(sht,data,3);
if(CheckCRC8ForSHT2x(data,2,data[2]))
{
result=(uint16_t)(data[0]);
result=(result<<8)+(uint16_t)(data[1]);
}
sht->humiCode=result;
return CalcSHT2xHumidity(result);
}
3 、驅動的使用
我們已經設計并實現了SHT2x溫濕度傳感器驅動,接下來我們還需要對這一驅動進行驗證,所以我們要基于此驅動設計一個簡單的應用。
3.1 、聲明并初始化對象
使用基于對象的操作我們需要先得到這個對象,所以我們先要使用前面定義的SHT2X溫濕度傳感器對象類型聲明一個SHT2X溫濕度傳感器對象變量,具體操作格式如下:
SHT2xObjectTypesht2x;
聲明了這個對象變量并不能立即使用,我們還需要使用驅動中定義的初始化函數對這個變量進行初始化。這個初始化函數所需要的輸入參數如下:
SHT2xObjectType*sht,SHT2X對象變量
SHT2xDPIType dpi,測量分辨率配置
SHT2xBatteryTypeendBat,電池結束狀態配置
SHT2xHeaterTypeheater,加熱器是否啟用配置
SHT2xOTPType otp,是否加載OTP配置
SHT2xTransmitwrite,寫操作指針
SHT2xReceive read,讀操作指針
SHT2xDelaymsdelayms,毫秒延時指針
對于這些參數,對象變量我們已經定義了。所使用的測量分辨率配置、電池結束狀態配置、加熱器是否啟用配置以及是否加載OTP配置均為枚舉,根據實際情況選擇就好了。主要的是我們需要定義幾個函數,并將函數指針作為參數。這幾個函數的類型如下:
/* 毫秒延時函數指針類型 */
typedef void (*SHT2xDelayms)(volatileuint32_t nTime);
/* 發送數據函數指針類型 */
typedef void (*SHT2xTransmit)(structSHT2xObject *sht,uint8_t *tData,uint16_t tSize);
/* 接收數據函數指針類型 */
typedef void (*SHT2xReceive)(structSHT2xObject *sht,uint8_t *rData,uint16_t rSize);
對于這幾個函數我們根據樣式定義就可以了,具體的操作可能與使用的硬件平臺有關系。所以我們定義在STM32平臺下使用硬件接口I2C收發器的函數。具體函數定義如下:
/*從SHT20接收數據*/
static voidReceiveFromSHT20(SHT2xObjectType *sht,uint8_t *rData,uint16_t rSize)
{
HAL_I2C_Master_Receive(&sht2xi2c,sht->devAddress,rData, rSize, 1000);
}
/*向SHT20傳送數據*/
static voidTransmitToSHT20(SHT2xObjectType *sht,uint8_t *tData,uint16_t tSize)
{
HAL_I2C_Master_Transmit(&sht2xi2c,sht->devAddress,tData,tSize,1000);
}
對于延時函數我們可以采用各種方法實現。我們采用的STM32平臺和HAL庫則可以直接使用HAL_Delay()函數。于是我們可以調用初始化函數如下:
SHT2xInitialization(&sht2x,SHT2x_DPI_RH12_T14,SHT2x_End_High,SHT2xHEATERDISABLE,SHT2xOTPDISABLE,TransmitToSHT20,ReceiveFromSHT20,HAL_Delay);
在這里我們將SHT2x溫濕度控制器對象變量初始化為:最高分辨率,在大于2.25V結束電池狀態,不加載OTP,不使用加熱器。
3.2 、基于對象進行操作
我們定義了對象變量并使用初始化函數給其作了初始化。接著我們就來考慮操作這一對象獲取我們想要的數據。我們在驅動中已經將獲取數據并轉換為相應的物理量值,接下來我們使用這一驅動開發我們的應用實例。
/* 獲取SHT2x溫適度數據 */
void GetSHT2xMeasureData(void)
{
float humidity;
float temperature;
humidity=GetSHT2xHumidityValue(&sht2x,MEASURE_RH_COMMAND_NOHOST);
temperature=GetSHT2xTemperatureValue(&sht2x,MEASURE_T_COMMAND_NOHOST);
}
這里我們設計了一個簡單的應用,直接獲取SHT2x溫濕度傳感器測量到的溫濕度數據。
4 、應用總結
因為SHT2x溫濕度傳感器采用的是標準I2C接口,所以在驅動設計中沒有考慮硬件接口相關的內容。我們只專注于SHT2x溫濕度傳感器的配置與操作。所以在使用驅動程序時,無論是使用硬件I2C收發控制器還是使用GPIO模擬的軟件收發控制都需要單獨做相應的配置。
我們已經設計并實現了SHT2x溫濕度傳感器的驅動程序,也使用這一驅動程序實現了讀取SHT2x溫濕度傳感器溫度、濕度數據的簡單應用。經我們測試所得到的結果是符合我們期望的,這也說明驅動程序的設計是成功的。
在使用驅動時還需注意,在做初始化配置時,對用戶寄存器的寫操作需注意不得變更預留位且相關的預留位的默認值以后可能會改變。因此,在進行任何寫用戶寄存器的操作之前,必須先讀預留位的默認值。而且在初始化配置時,還要注意SHT2X 中OTP功能默認為禁止狀態,且不推薦用戶使用。
評論
查看更多