|
本帖最后由 51黑ren 于 2015-12-27 04:09 編輯
首先講講SHT10這款溫室度傳感器。SHT1x(包括SHT10,SHT11和SHT15)屬于Sersirion溫濕度傳感器家族中的貼片封裝系列。更之前我講過的DHT11這款溫濕度傳感器相比,體積小了許多,特別適合用于產(chǎn)品中。SHT10溫濕度傳感器包括一個電容性聚合體測濕敏感元件、一個用能隙材料制成的測溫元件(文縐縐的),傳感器內(nèi)部有一個精度高達(dá)14為位的A/D轉(zhuǎn)換器,適應(yīng)串行接口電路實(shí)現(xiàn)無縫連接。該產(chǎn)品具有品質(zhì)卓越、響應(yīng)速度速度快,抗干擾能力強(qiáng)、性價比高等優(yōu)點(diǎn)。
1、接口定義:
SHT10的接口定義如下圖所示:

如上圖所示,1腳為GND,4腳為VDD。它的供電電壓范圍為2.4~5.5V,建議的電壓為3.3V,在電源引腳(VDD、GND)之間必須加上一個0.1uf的電容,應(yīng)于去耦濾波用。它的2腳DATA為數(shù)據(jù)引腳,3腳SCK為時鐘控制引腳,沒有發(fā)現(xiàn)這兩個引腳很像IIC所使用的引腳功能?沒錯,這個傳感器確實(shí)可以認(rèn)為是IIC接口,但是又有卻別。該傳感器不能按照IIC的協(xié)議編址,但是,如果IIC總線上沒有掛接別的元件,傳感器可以直接連到IIC總線上,但是單片機(jī)必須按照傳感器的協(xié)議工作。傳感器與單片機(jī)的接線如下圖所示:

2、傳感器的通訊
2.1、“啟動傳輸”時序
用一組“啟動傳輸”時序來完成數(shù)據(jù)傳輸?shù)某跏蓟Kǎ寒?dāng)SCK時鐘高電平時DATA翻轉(zhuǎn)為低電平,緊接著SCK變成低電平,隨后是在SCK時鐘高電平,隨后是在SCK時鐘高電平DATA翻轉(zhuǎn)位高電平。時序如下:

2.2、復(fù)位時序
如果與SHT1x 通訊中斷,可通過下列信號時序復(fù)位:當(dāng)DATA 保持高電平時,觸發(fā)SCK 時鐘9 次或更多。時序圖如下:

2.3、命令集
傳感器的命令包含三個地址位(目前只支持000,這就是他只能掛接在空閑的IIC總線上的原因)和五個命令位。。SHT1x 會以下述方式表示已正確地接收到指令:在第8 個SCK 時鐘的下降沿之后,將DATA 下拉為低電平(ACK 位)。在第9 個SCK 時鐘的下降沿之后,釋放DATA(恢復(fù)高電平)。命令集如下:

2.4、溫濕度測量
發(fā)布一組測量命令(‘00000101’表示相對濕度RH,‘00000011’表示溫度T)后,控制器要等待測量結(jié)束。這個過程需要大約20/80/320ms,分別對應(yīng)8/12/14bit 測量。確切的時間隨內(nèi)部晶振速度,最多可能有-30%的變化。。SHT1x 通過下拉DATA 至低電平并進(jìn)入空閑模式,表示測量的結(jié)束。控制器在再次觸發(fā)SCK 時鐘前,必須等待這個“數(shù)據(jù)備妥”信號來讀出數(shù)據(jù)。檢測數(shù)據(jù)可以先被存儲,這樣控制器可以繼續(xù)執(zhí)行其它任務(wù)在需要時再讀出數(shù)據(jù)。
在收到CRC 的確認(rèn)位之后,表明通訊結(jié)束。如果不使用CRC-8 校驗(yàn),控制器可以在測量值LSB 后,通過保持ACK高電平終止通訊。在測量和通訊完成后,SHT1x 自動轉(zhuǎn)入休眠模式。
2.5、狀態(tài)寄存器
SHT1x 的某些高級功能可以通過給狀態(tài)寄存器發(fā)送指令來實(shí)現(xiàn),如選擇測量分辨率,電量不足提醒,使用 OTP 加載或啟動加熱功能等。狀態(tài)寄存器度、寫如下:
狀態(tài)寄存器寫
狀態(tài)寄存器讀
狀態(tài)寄存器的具體描述如下表所示:
測量分辨率:默認(rèn)分辨率 14bit (溫度) 和 12bit (濕度) 可以被降低為 12 和 8bit. 尤其適用于要求測量速度極高或者功耗極低的應(yīng)用。
電量不足檢測功能:在電壓不足 2.47V 發(fā)出警告。精度為±0.05 V。
加熱:可通過向狀態(tài)寄存器內(nèi)寫入命令啟動傳感器內(nèi)部加熱器.。加熱器可以使傳感器的溫度高于周圍環(huán)境 5 – 10°C12 。功耗大約為 8mA @ 5V 。
OPT加載:開啟此功能,標(biāo)定數(shù)據(jù)將在每次測量前被上傳到寄存器。如果不開啟此功能,可減少大約 10ms的測量時間。
上面的寄存器如果沒有什么特殊要求或應(yīng)用于特定的場合,則無需配置,選擇默認(rèn)就可以了。
2.6、通訊過程
傳感器的通訊過程為:發(fā)送”啟動傳輸“時序,初始化傳感器——>發(fā)送命令——>等待傳感器應(yīng)答,及測量結(jié)束——>接收傳感器的16位數(shù)據(jù)值——>接收8為的CRC校驗(yàn)數(shù)據(jù)——>休眠,等待下一次傳輸開始。
傳輸?shù)倪^程的測量時序可以由下圖示意:
上圖中 TS = 傳輸開始, MSB = 高有效字節(jié),LSB =低有效字節(jié), LSb = 低有效位。
下面舉個實(shí)際測量時的相對濕度測量時序例子。時序如下:
這張圖可以知道:我們接收到的數(shù)據(jù)數(shù)值為”0000 0100 0011 0001“ = 1073 = 35.50% RH (位含溫度補(bǔ)償),至于怎么計算的,請接著往下看。
2.7、信號轉(zhuǎn)化
2.7.1 溫度的轉(zhuǎn)化
設(shè)T 2 1 SOt為從傳感器上讀出來的測量數(shù)值,我們需要用下面的公式將測量數(shù)值轉(zhuǎn)換成整整的溫度值。
T = d1 + d2 * SOt (其中d1,d2的值根據(jù)實(shí)際情況選擇,選項(xiàng)如下)
2.7.2 濕度的轉(zhuǎn)換
濕度的轉(zhuǎn)換公式如下: 。其中濕度的轉(zhuǎn)化參數(shù)如下選擇:根據(jù)采樣的精度不同而不同。
99%以上的濕度已經(jīng)接近飽和必須經(jīng)過處理顯示100%RH13.請注意 濕度傳感器對電壓無依賴性。測量值與相對濕度的轉(zhuǎn)化如下圖所示:
相對濕度根據(jù)上面的參數(shù)與公式算出來之后,還需要考慮當(dāng)前環(huán)境溫度而進(jìn)行適當(dāng)?shù)难a(bǔ)償。補(bǔ)償?shù)墓郊捌鋮?shù)選擇如下:
2.7.3、露點(diǎn)的計算
露點(diǎn)的定義:露點(diǎn)溫度指空氣在此溫度下能保持最多的水汽,當(dāng)溫度冷卻到露點(diǎn),空氣變得飽和,就會出現(xiàn)霧、露或霜。
SHT1x 并不直接進(jìn)行露點(diǎn)測量,,但露點(diǎn)可以通過溫度和濕度讀數(shù)計算得到.。由于溫度和濕度在同一塊集成電路上測量,SHT1x 可測量露點(diǎn)。 一塊集成電路上測量,SHT1x 可測量露點(diǎn)。 下面直接給出結(jié)論性的露點(diǎn)計算公式了。
LogEW=(0.66077+7.5*T/(237.3+T)+(log10(RH)-2)
露點(diǎn):Dp=((0.66077-logEW)*237.3/(logEW-8.16077)
例如:RH=10% T=25C ->EW=23.7465->露點(diǎn)=-8.69℃
RH=90% T=50C ->EW=92.4753->露點(diǎn)=47.89℃
2.8、STM32上的SHT10驅(qū)動程序
2.8.1、SHT10.h文件的編寫
這個文件主要定義些重要的參數(shù),以及更硬件相關(guān)的一些定義。
- /*************************************************************
- \(^o^)/
- Copyright (C), 2013-2020, ZheJiang University of Technology
- File name : SHT10.h
- Author : ziye334
- Version : V1.0
- Data : 2014/3/10
- Description: Digital temperature and humidity sensor driver code
-
- *************************************************************/
- #ifndef __SHT10_H__
- #define __SHT10_H__
- #include "stm32f10x.h"
- enum {TEMP, HUMI};
- /* GPIO相關(guān)宏定義 */
- #define SHT10_AHB2_CLK RCC_APB2Periph_GPIOD
- #define SHT10_DATA_PIN GPIO_Pin_0
- #define SHT10_SCK_PIN GPIO_Pin_1
- #define SHT10_DATA_PORT GPIOD
- #define SHT10_SCK_PORT GPIOD
- #define SHT10_DATA_H() GPIO_SetBits(SHT10_DATA_PORT, SHT10_DATA_PIN) //拉高DATA數(shù)據(jù)線
- #define SHT10_DATA_L() GPIO_ResetBits(SHT10_DATA_PORT, SHT10_DATA_PIN) //拉低DATA數(shù)據(jù)線
- #define SHT10_DATA_R() GPIO_ReadInputDataBit(SHT10_DATA_PORT, SHT10_DATA_PIN) //讀DATA數(shù)據(jù)線
- #define SHT10_SCK_H() GPIO_SetBits(SHT10_SCK_PORT, SHT10_SCK_PIN) //拉高SCK時鐘線
- #define SHT10_SCK_L() GPIO_ResetBits(SHT10_SCK_PORT, SHT10_SCK_PIN) //拉低SCK時鐘線
- /* 傳感器相關(guān)宏定義 */
- #define noACK 0
- #define ACK 1
- //addr command r/w
- #define STATUS_REG_W 0x06 //000 0011 0 寫狀態(tài)寄存器
- #define STATUS_REG_R 0x07 //000 0011 1 讀狀態(tài)寄存器
- #define MEASURE_TEMP 0x03 //000 0001 1 測量溫度
- #define MEASURE_HUMI 0x05 //000 0010 1 測量濕度
- #define SOFTRESET 0x1E //000 1111 0 復(fù)位
- void SHT10_Config(void);
- void SHT10_ConReset(void);
- u8 SHT10_SoftReset(void);
- u8 SHT10_Measure(u16 *p_value, u8 *p_checksum, u8 mode);
- void SHT10_Calculate(u16 t, u16 rh,float *p_temperature, float *p_humidity);
- float SHT10_CalcuDewPoint(float t, float h);
- #endif
復(fù)制代碼
2.8.2、SHT10.c驅(qū)動程序的編寫
不廢話了,直接貼代碼:
- /*************************************************************
- \(^o^)/
- Copyright (C), 2013-2020, ZheJiang University of Technology
- File name : SHT10.c
- Author : ziye334
- Version : V1.0
- Data : 2014/3/10
- Description: Digital temperature and humidity sensor driver code
-
- *************************************************************/
- #include "SHT10.h"
- #include <math.h>
- /*************************************************************
- Function :SHT10_Dly
- Description:SHT10時序需要的延時
- Input : none
- return : none
- *************************************************************/
- void SHT10_Dly(void)
- {
- u16 i;
- for(i = 500; i > 0; i--);
- }
- /*************************************************************
- Function :SHT10_Config
- Description:初始化 SHT10引腳
- Input : none
- return : none
- *************************************************************/
- void SHT10_Config(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- //初始化SHT10引腳時鐘
- RCC_APB2PeriphClockCmd(SHT10_AHB2_CLK ,ENABLE);
-
- //PD0 DATA 推挽輸出
- GPIO_InitStructure.GPIO_Pin = SHT10_DATA_PIN;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_Init(SHT10_DATA_PORT, &GPIO_InitStructure);
- //PD1 SCK 推挽輸出
- GPIO_InitStructure.GPIO_Pin = SHT10_SCK_PIN;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_Init(SHT10_SCK_PORT, &GPIO_InitStructure);
- SHT10_ConReset(); //復(fù)位通訊
- }
- /*************************************************************
- Function :SHT10_DATAOut
- Description:設(shè)置DATA引腳為輸出
- Input : none
- return : none
- *************************************************************/
- void SHT10_DATAOut(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- //PD0 DATA 推挽輸出
- GPIO_InitStructure.GPIO_Pin = SHT10_DATA_PIN;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_Init(SHT10_DATA_PORT, &GPIO_InitStructure);
- }
- /*************************************************************
- Function :SHT10_DATAIn
- Description:設(shè)置DATA引腳為輸入
- Input : none
- return : none
- *************************************************************/
- void SHT10_DATAIn(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- //PD0 DATA 浮動輸入
- GPIO_InitStructure.GPIO_Pin = SHT10_DATA_PIN;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(SHT10_DATA_PORT, &GPIO_InitStructure);
- }
- /*************************************************************
- Function :SHT10_WriteByte
- Description:寫1字節(jié)
- Input : value:要寫入的字節(jié)
- return : err: 0-正確 1-錯誤
- *************************************************************/
- u8 SHT10_WriteByte(u8 value)
- {
- u8 i, err = 0;
-
- SHT10_DATAOut(); //設(shè)置DATA數(shù)據(jù)線為輸出
- for(i = 0x80; i > 0; i /= 2) //寫1個字節(jié)
- {
- if(i & value)
- SHT10_DATA_H();
- else
- SHT10_DATA_L();
- SHT10_Dly();
- SHT10_SCK_H();
- SHT10_Dly();
- SHT10_SCK_L();
- SHT10_Dly();
- }
- SHT10_DATAIn(); //設(shè)置DATA數(shù)據(jù)線為輸入,釋放DATA線
- SHT10_SCK_H();
- err = SHT10_DATA_R(); //讀取SHT10的應(yīng)答位
- SHT10_SCK_L();
- return err;
- }
- /*************************************************************
- Function :SHT10_ReadByte
- Description:讀1字節(jié)數(shù)據(jù)
- Input : Ack: 0-不應(yīng)答 1-應(yīng)答
- return : err: 0-正確 1-錯誤
- *************************************************************/
- u8 SHT10_ReadByte(u8 Ack)
- {
- u8 i, val = 0;
- SHT10_DATAIn(); //設(shè)置DATA數(shù)據(jù)線為輸入
- for(i = 0x80; i > 0; i /= 2) //讀取1字節(jié)的數(shù)據(jù)
- {
- SHT10_Dly();
- SHT10_SCK_H();
- SHT10_Dly();
- if(SHT10_DATA_R())
- val = (val | i);
- SHT10_SCK_L();
- }
- SHT10_DATAOut(); //設(shè)置DATA數(shù)據(jù)線為輸出
- if(Ack)
- SHT10_DATA_L(); //應(yīng)答,則會接下去讀接下去的數(shù)據(jù)(校驗(yàn)數(shù)據(jù))
- else
- SHT10_DATA_H(); //不應(yīng)答,數(shù)據(jù)至此結(jié)束
- SHT10_Dly();
- SHT10_SCK_H();
- SHT10_Dly();
- SHT10_SCK_L();
- SHT10_Dly();
- return val; //返回讀到的值
- }
- /*************************************************************
- Function :SHT10_TransStart
- Description:開始傳輸信號,時序如下:
- _____ ________
- DATA: |_______|
- ___ ___
- SCK : ___| |___| |______
- Input : none
- return : none
- *************************************************************/
- void SHT10_TransStart(void)
- {
- SHT10_DATAOut(); //設(shè)置DATA數(shù)據(jù)線為輸出
- SHT10_DATA_H();
- SHT10_SCK_L();
- SHT10_Dly();
- SHT10_SCK_H();
- SHT10_Dly();
- SHT10_DATA_L();
- SHT10_Dly();
- SHT10_SCK_L();
- SHT10_Dly();
- SHT10_SCK_H();
- SHT10_Dly();
- SHT10_DATA_H();
- SHT10_Dly();
- SHT10_SCK_L();
- }
- /*************************************************************
- Function :SHT10_ConReset
- Description:通訊復(fù)位,時序如下:
- _____________________________________________________ ________
- DATA: |_______|
- _ _ _ _ _ _ _ _ _ ___ ___
- SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______| |___| |______
- Input : none
- return : none
- *************************************************************/
- void SHT10_ConReset(void)
- {
- u8 i;
- SHT10_DATAOut();
- SHT10_DATA_H();
- SHT10_SCK_L();
- for(i = 0; i < 9; i++) //觸發(fā)SCK時鐘9c次
- {
- SHT10_SCK_H();
- SHT10_Dly();
- SHT10_SCK_L();
- SHT10_Dly();
- }
- SHT10_TransStart(); //啟動傳輸
- }
- /*************************************************************
- Function :SHT10_SoftReset
- Description:軟復(fù)位
- Input : none
- return : err: 0-正確 1-錯誤
- *************************************************************/
- u8 SHT10_SoftReset(void)
- {
- u8 err = 0;
- SHT10_ConReset(); //通訊復(fù)位
- err += SHT10_WriteByte(SOFTRESET);//寫RESET復(fù)位命令
- return err;
- }
- /*************************************************************
- Function :SHT10_ReadStatusReg
- Description:讀狀態(tài)寄存器
- Input : p_value-讀到的數(shù)據(jù);p_checksun-讀到的校驗(yàn)數(shù)據(jù)
- return : err: 0-正確 0-錯誤
- *************************************************************/
- u8 SHT10_ReadStatusReg(u8 *p_value, u8 *p_checksum)
- {
- u8 err = 0;
- SHT10_TransStart(); //開始傳輸
- err = SHT10_WriteByte(STATUS_REG_R);//寫STATUS_REG_R讀取狀態(tài)寄存器命令
- *p_value = SHT10_ReadByte(ACK); //讀取狀態(tài)數(shù)據(jù)
- *p_checksum = SHT10_ReadByte(noACK);//讀取檢驗(yàn)和數(shù)據(jù)
-
- return err;
- }
- /*************************************************************
- Function :SHT10_WriteStatusReg
- Description:寫狀態(tài)寄存器
- Input : p_value-要寫入的數(shù)據(jù)值
- return : err: 0-正確 1-錯誤
- *************************************************************/
- u8 SHT10_WriteStatusReg(u8 *p_value)
- {
- u8 err = 0;
- SHT10_TransStart(); //開始傳輸
- err += SHT10_WriteByte(STATUS_REG_W);//寫STATUS_REG_W寫狀態(tài)寄存器命令
- err += SHT10_WriteByte(*p_value); //寫入配置值
- return err;
- }
- /*************************************************************
- Function :SHT10_Measure
- Description:從溫濕度傳感器讀取溫濕度
- Input : p_value-讀到的值;p_checksum-讀到的校驗(yàn)數(shù)
- return : err: 0-正確 1—錯誤
- *************************************************************/
- u8 SHT10_Measure(u16 *p_value, u8 *p_checksum, u8 mode)
- {
- u8 err = 0;
- u32 i;
- u8 value_H = 0;
- u8 value_L = 0;
- SHT10_TransStart(); //開始傳輸
- switch(mode)
- {
- case TEMP: //測量溫度
- err += SHT10_WriteByte(MEASURE_TEMP);//寫MEASURE_TEMP測量溫度命令
- break;
- case HUMI:
- err += SHT10_WriteByte(MEASURE_HUMI);//寫MEASURE_HUMI測量濕度命令
- break;
- default:
- break;
- }
- SHT10_DATAIn();
- for(i = 0; i < 72000000; i++) //等待DATA信號被拉低
- {
- if(SHT10_DATA_R() == 0) break; //檢測到DATA被拉低了,跳出循環(huán)
- }
- if(SHT10_DATA_R() == 1) //如果等待超時了
- err += 1;
- value_H = SHT10_ReadByte(ACK);
- value_L = SHT10_ReadByte(ACK);
- *p_checksum = SHT10_ReadByte(noACK); //讀取校驗(yàn)數(shù)據(jù)
- *p_value = (value_H << 8) | value_L;
- return err;
- }
- /*************************************************************
- Function :SHT10_Calculate
- Description:計算溫濕度的值
- Input : Temp-從傳感器讀出的溫度值;Humi-從傳感器讀出的濕度值
- p_humidity-計算出的實(shí)際的濕度值;p_temperature-計算出的實(shí)際溫度值
- return : none
- *************************************************************/
- void SHT10_Calculate(u16 t, u16 rh, float *p_temperature, float *p_humidity)
- {
- const float d1 = -39.7;
- const float d2 = +0.01;
- const float C1 = -2.0468;
- const float C2 = +0.0367;
- const float C3 = -0.0000015955;
- const float T1 = +0.01;
- const float T2 = +0.00008;
- float RH_Lin; //RH線性值
- float RH_Ture; //RH真實(shí)值
- float temp_C;
- temp_C = d1 + d2 * t; //計算溫度值
- RH_Lin = C1 + C2 * rh + C3 * rh * rh; //計算濕度值
- RH_Ture = (temp_C -25) * (T1 + T2 * rh) + RH_Lin; //濕度的溫度補(bǔ)償,計算實(shí)際的濕度值
- if(RH_Ture > 100) //設(shè)置濕度值上限
- RH_Ture = 100;
- if(RH_Ture < 0.1)
- RH_Ture = 0.1; //設(shè)置濕度值下限
- *p_humidity = RH_Ture;
- *p_temperature = temp_C;
- }
- /*************************************************************
- Function :SHT10_CalcuDewPoint
- Description:計算露點(diǎn)
- Input : h-實(shí)際的濕度;t-實(shí)際的溫度
- return : dew_point-露點(diǎn)
- *************************************************************/
- float SHT10_CalcuDewPoint(float t, float h)
- {
- float logEx, dew_point;
- logEx = 0.66077 + 7.5 * t / (237.3 + t) + (log10(h) - 2);
- dew_point = ((0.66077 - logEx) * 237.3) / (logEx - 8.16077);
- return dew_point;
- }
- 2.8.3、main函數(shù)的編寫:
- int main(void)
- {
- u16 humi_val, temp_val;
- u8 err = 0, checksum = 0;
- float humi_val_real = 0.0;
- float temp_val_real = 0.0;
- float dew_point = 0.0;
-
- BSP_Init();
- printf("\nSHT10溫室度測試程序!!!\n");
- SHT10_Config();
- while(1)
- {
- err += SHT10_Measure(&temp_val, &checksum, TEMP); //獲取溫度測量值
- err += SHT10_Measure(&humi_val, &checksum, HUMI); //獲取濕度測量值
- if(err != 0)
- SHT10_ConReset();
- else
- {
- SHT10_Calculate(temp_val, humi_val, &temp_val_real, &humi_val_real); //計算實(shí)際的溫濕度值
- dew_point = SHT10_CalcuDewPoint(temp_val_real, humi_val_real); //計算露點(diǎn)溫度
- }
- printf("當(dāng)前環(huán)境溫度為:%2.1f℃,濕度為:%2.1f%%,露點(diǎn)溫度為%2.1f℃\r\n", temp_val_real, humi_val_real, dew_point);
- LED1_Toggle();
- Delay_ms(1000);
- }
- }
復(fù)制代碼
|
|