1、SHTC3簡單說明
SHTC3是一個檢測溫度、濕度的傳感器,可以檢測-40℃~125℃的溫度范圍和0%~100%的濕度范圍。
SHTC3的工作電壓范圍為:1.62V~3.6V。
SHTC3使用的通訊方式是I2C,通訊速率可以達到400KHz。
SHTC3的管腳圖如下:
從圖中可以看到,SHTC3只有4個引腳,電源和地、2個I2C通訊引腳。
關於SHTC3更多說明,可以查看它的規格資料。
2、SHTC3的設備地址和命令
在SHTC3的規格資料內,SHTC3的I2C設備地址為0x70,如下:
在實際的使用過程中,SHTC3的設備地址需要與讀寫數據/命令方向位組成一個字節同時發送,字節的最低位為讀寫數據/命令方向位,高7位是SHTC3的設備地址。
如果要通過I2C寫數據或命令給SHTC3,在I2C起始信號之后,需要發送“1110 0000”,即0xE0給SHTC3,除了通過高7位“1110 000”的設備地址尋址還通過最低位“0”通知SHTC3接下來是寫數據或命令操作。
如果要通過I2C讀取SHTC3中的數據,在I2C起始信號之后,需要發送“1110 0001”,即0xE1給SHTC3,除了通過高7位“1110 000”的設備地址尋址還通過最低位“0”通知SHTC3接下來是讀取數據的操作。
SHTC3的命令由2個字節組成,在發送命令時,主機需要通過I2C發送2個字節命令給SHTC3。SHTC3有如下命令:
1 //SHTC3地址
2 #define SHTC3_ADDRESS 0x70
3
4 //SHTC3 命令
5 #define SHTC3_WIRTE_CMD ((SHTC3_ADDRESS<<1)&0xFE)
6 #define SHTC3_READ_CMD ((SHTC3_ADDRESS<<1)|0x01)
7
8 #define SHTC3_SOFT_RESET_CMD 0x805D//軟件復位命令
9 #define SHTC3_READ_ID_CMD 0xEFC8//讀取SHTC3 ID命令
10 #define SHTC3_WAKE_UP_CMD 0x3517//將芯片從睡眠模式喚醒命令
11 #define SHTC3_SLEEP_CMD 0xB098//使芯片進入休眠命令
12
13 //Normal Mode Clock Stretching Enable Measurement Command
14 #define SHTC3_NOR_READ_TEMP_FIR_EN_CMD 0x7CA2//
15 #define SHTC3_NOR_READ_HUM_FIR_EN_CMD 0x5C24//
16
17 //Normal Mode Clock Stretching Disable Measurement Command
18 #define SHTC3_NOR_READ_TEMP_FIR_DIS_CMD 0x7866//
19 #define SHTC3_NOR_READ_HUM_FIR_DIS_CMD 0x58E0//
20
21 //Low Power Mode Clock Stretching Enable Measurement Command
22 #define SHTC3_LOW_READ_TEMP_FIR_EN_CMD 0x6458//
23 #define SHTC3_LOW_READ_HUM_FIR_EN_CMD 0x44DE//
24
25 //Low Power Mode Clock Stretching Disable Measurement Command
26 #define SHTC3_LOW_READ_TEMP_FIR_DIS_CMD 0x609C//
27 #define SHTC3_LOW_READ_HUM_FIR_DIS_CMD 0x401A//
主機發送2個字節命令給SHTC3的代碼如下:
1 void SHTC3_WRITE_CMD(uint16_t cmd) 2 { 3 I2C_START(); 4 SHTC3_ERR = I2C_WRITE_BYTE(SHTC3_WIRTE_CMD); 5 if(SHTC3_ERR != 0) 6 { 7 SHTC3_ERR = I2C_WRITE_BYTE((cmd>>8) & 0xFF); 8 if(SHTC3_ERR != 0) 9 { 10 SHTC3_ERR = I2C_WRITE_BYTE(cmd & 0xFF); 11 if(SHTC3_ERR != 0) 12 { 13 I2C_STOP(); 14 } 15 } 16 } 17 }
SHTC3_ERR變量的作用主要是檢測是否能收到SHTC3的應答信號,如果沒有收到應答信號就不再進行后面的操作。
SHTC3_SOFT_RESET_CMD是SHTC3的軟件復位命令,主機通過發送該命令來復位SHTC3。一般在上電初始化時,主機通過發送該命令來復位一下SHTC3。通過調用SHTC3_WRITE_CMD(SHTC3_SOFT_RESET_CMD)函數來軟件復位SHTC3。
SHTC3有一個16bit的ID寄存器,主機可以通過讀取該寄存器的值來判斷與SHTC3的通訊是否正常。該ID寄存器內保存的值如下:
上圖中的"x"表示無效值,將ID寄存器的值讀取回來之后,只需要去比較bit11位和bit5~bit0位的值就好,將其它位屏蔽掉之后的值為0x0807。主機讀取SHTC3 ID寄存器的值的代碼如下:
1 void SHTC3_READ_ID(uint16_t cmd) 2 { 3 SHTC3_ID = 0; 4
5 SHTC3_WRITE_CMD(SHTC3_READ_ID_CMD); 6 if(SHTC3_ERR != 0) 7 { 8 I2C_START(); 9 SHTC3_ERR = I2C_WRITE_BYTE(SHTC3_READ_CMD); 10 if(SHTC3_ERR != 0) 11 { 12 SHTC3_ID = I2C_READ_BYTE(1); 13 SHTC3_ID <<= 8; 14 SHTC3_ID |= I2C_READ_BYTE(0); 15 I2C_STOP(); 16
17 SHTC3_ID &= 0x083F; 18 } 19 } 20 }
從SHTC3的ID寄存器讀取回來的數據再與上0x083F,去除掉不需要用到的部分bit。
SHTC3_WAKE_UP_CMD和SHTC3_SLEEP_CMD是SHTC3的休眠喚醒和進入休眠命令,在使用的過程中,為了減少功耗,在不需要測量數據的時候,一般讓SHTC3處於休眠狀態。在需要測量溫濕度的時候,再通過發送SHTC3_WAKE_UP_CMD命令來喚醒SHTC3,但是需要注意的是,SHTC3在喚醒之后需要一段穩定的時候,只有在SHC3穩定之后主機才能發送測量命令給SHTC3。SHTC3的休眠喚醒和進入休眠的代碼如下:
1 void SHTC3_WAKE_UP(void) 2 { 3 SHTC3_WRITE_CMD(SHTC3_WAKE_UP_CMD); 4
5 if(SHTC3_ERR != 0)//沒有收到響應信號,直接退出
6 { 7 I2C_STOP(); 8 //正常休眠喚醒之后需要等待一段穩定的時間發送命令,SHTC3才能響應主機
9 I2C_DELAY(5000);//大約1ms
10 } 11 } 12
13 void SHTC3_INTO_SLEEP(void) 14 { 15 SHTC3_WRITE_CMD(SHTC3_SLEEP_CMD); 16 I2C_STOP(); 17 }
上面的SHTC3_WAKE_UP函數在發送完SHTC3_WAKE_UP_CMD命令之后,如果收到SHTC3的應答信號,說明命令發送成功了,在發送完結束信號之后,會通過一個軟件延時等待SHTC3穩定。
在使用SHTC3時,需要注意的是,如果SHTC3處於休眠的狀態,那么SHTC3只能響應喚醒命令,如果主機在SHTC3休眠的狀態下發送其它命令,那么SHTC3是不會反饋應答信號給主機的。
SHTC3上電初始化代碼如下:
1 void SHTC3_Init(void) 2 { 3 I2C_Init(); 4
5 SHTC3_WAKE_UP();//為了防止仿真的時候SHTC3再SLEEP狀態下復位運行時造成SHTC3無法響應主機發送的命令,由於在仿真的時候SHTC3芯片沒有斷電,還是處於休眠狀態,SHTC3在休眠是無法響應除了喚醒命令的其它操作的
6
7 SHTC3_WRITE_CMD(SHTC3_SOFT_RESET_CMD);//發送軟件復位命令
8 HAL_Delay(10);//延時等待復位穩定
9
10 SHTC3_READ_ID(SHTC3_READ_ID_CMD); 11
12 printf("SHTC3的ID值為:0x%04x\r\n",SHTC3_ID); 13 }
首先調用I2C_Init()函數配置I2C的引腳。然后通過調用SHTC3_WAKE_UP()函數喚醒SHTC3,這一步不是必須的,這只是為了防止在仿真的時候復位運行時,HTC3處於休眠的狀態從而導致無法響應主機發送的復位命令。
發送完喚醒命令之后,主機接着發送復位命令給SHTC3,讓SHTC3軟復位,SHTC3復位后需要一段穩定的時間,所以使用延時等待一下。最后讀取SHTC3的ID值並通過USART打印出來,用來檢驗讀取到的ID值是否正確。
3、SHTC3測量溫度濕度命令和步驟
SHTC3有多個測量溫度濕度的命令,如下:
在這里使用的是Normal Mode中的命令來測量數據,Low Power Mode不知道有什么區別。
從上面的命令表中可以看到,測量命令除了讀取回來的數據先后順序有區別,還有一個Clock Stretching Enabled和Clock Stretching Disabled的區別。
Clock Stretching是時鍾拉伸的意思。如果使用Clock Stretching Enable命令的話,那么發送完測量命令之后,在SHTC3測量溫度濕度數據的過程中,SHTC3會拉低I2C的時鍾線SCL,通過這樣來禁止主機發送命令給SHTC3,只有當SHTC3完成溫度濕度數據測量時,SHTC3才會釋放時鍾線SCL。
如果使用Clock Stretching Disable命令的話,在SHTC3測量數據的過程中,SHTC3並不會拉低I2C的時鍾線SCL,只是如果主機在SHTC3測量數據的過程中發送命令或數據的時候,SHTC3是不會響應主機的,主機可以通過SHTC3是否有響應信號來判斷SHTC3是否完成數據的測量。
在SHTC3數據手冊中有說道,每一個測量周期包含4個命令部分,如下:
1、發送喚醒命令。
2、發送測量命令
3、讀取測量完成之后的數據。
4、發送休眠命令。
SHTC3測量示例如下圖所示:
主機首先發送休眠喚醒命令使SHTC3從休眠的狀態喚醒,發送完休眠喚醒命令之后,需要等待SHTC3喚醒並且穩定。
接着發送測量命令,SHTC3在接收到測量命令之后就開始測量數據了。
上面的圖中出現了Clock Stretching enabled和Clock Stretching disabled兩個分支,這是根據發送的測量命令的不同而導致的。
如果使用的是Clock Stretching enabled測量命令,那么在SHTC3在測量數據的過程中,當主機發送設備地址和讀位給SHTC3后,SHTC3在應答一個信號之后就會將SCL時鍾線拉低,主機在這個時候就無法與SHTC3通訊,只有在SHTC3測量完數據釋放SCL后,主機才讀取到SHTC3測量完的數據。
如果使用的是Clock Stretching disabled測量命令,么在SHTC3在測量數據的過程中,當主機發送設備地址和讀位給SHTC3,SHTC3不會產生應答信號(NACK)給主機,主機可以通過不斷發送命令然后查詢是否收到ACK信號來判斷SHTC3是否完成測量。
當SHTC3完成數據的測量,主機就可以讀取SHTC3中的溫度和濕度的數據了,溫度數據包含2個字節的數據和1個字節的CRC校驗數據,通用濕度的數據也包含2個字節的數據和1個字節的CRC校驗數據。
在完成數據的讀取操作之后,主機發送休眠命令給SHTC3,使SHTC3在不工作的時候休眠從而降低功耗。
讀取到的溫度和濕度數據是帶有CRC校驗的,可以通過CRC校驗檢驗數據是否正確。SHTC3的CRC校驗如下:
SHTC3的CRC校驗代碼如下:
1 uint8_t SHTC3_CRC_CHECK(uint16_t DAT,uint8_t CRC_DAT) 2 { 3 uint8_t i,t,temp; 4 uint8_t CRC_BYTE; 5
6 CRC_BYTE = 0xFF; 7 temp = (DAT>>8) & 0xFF; 8
9 for(t = 0;t < 2;t ++) 10 { 11 CRC_BYTE ^= temp; 12 for(i = 0;i < 8;i ++) 13 { 14 if(CRC_BYTE & 0x80) 15 { 16 CRC_BYTE <<= 1; 17
18 CRC_BYTE ^= 0x31; 19 } 20 else
21 { 22 CRC_BYTE <<= 1; 23 } 24 } 25
26 if(t == 0) 27 { 28 temp = DAT & 0xFF; 29 } 30 } 31
32 if(CRC_BYTE == CRC_DAT) 33 { 34 temp = 0; 35 } 36 else
37 { 38 temp = 1; 39 } 40
41 return temp; 42 }
在SHTC3資料中已經給出了計算溫度和濕度的公式,如下:
SRH和ST是從SHTC3采集回來的數據。
SHTC3完成一次測量的代碼如下:
1 void SHTC3_MEASUREMENT_TEMP_HUM(void) 2 { 3 uint8_t Cnt; 4 uint8_t Temp_Check_Num; 5 uint8_t Hum_Check_Num; 6
7 uint16_t TEMP_MEASUREMENT; 8 uint16_t HUM_MEASUREMENT; 9
10 uint32_t result; 11
12 SHTC3_WAKE_UP(); 13
14 if(SHTC3_ERR != 0) 15 { 16 SHTC3_WRITE_CMD(SHTC3_NOR_READ_TEMP_FIR_DIS_CMD);//SHTC3大約11ms~20ms檢測一次溫度
17
18 if(SHTC3_ERR != 0) 19 { 20 Cnt = 0; 21 do//等待SHTC3檢測完成,
22 { 23 I2C_DELAY(5000);//大約1ms
24 I2C_START(); 25 SHTC3_ERR = I2C_WRITE_BYTE(SHTC3_READ_CMD); 26 Cnt++; 27 if(Cnt == 25)//防止讀不到響應時,程序卡死
28 { 29 break; 30 } 31
32 }while(SHTC3_ERR == 0);//正常讀取到響應才退出
33
34 if(SHTC3_ERR != 0) 35 { 36 //SHTC3檢測完成,開始讀取數據,連CRC總共6個byte
37 TEMP_MEASUREMENT = I2C_READ_BYTE(1);//溫度數值高8位
38 TEMP_MEASUREMENT <<= 8; 39 TEMP_MEASUREMENT |= I2C_READ_BYTE(1);//溫度數值低8位
40 Temp_Check_Num = I2C_READ_BYTE(1);//溫度CRC校驗
41
42 HUM_MEASUREMENT = I2C_READ_BYTE(1); 43 HUM_MEASUREMENT <<= 8; 44 HUM_MEASUREMENT |= I2C_READ_BYTE(1); 45 Hum_Check_Num = I2C_READ_BYTE(0); 46
47 I2C_STOP(); 48
49 Cnt = SHTC3_CRC_CHECK(TEMP_MEASUREMENT,Temp_Check_Num); 50 if(Cnt == 0) 51 { 52 result = TEMP_MEASUREMENT*175*10;//保留一位小數點
53 TEMP_DATA = (uint16_t)(result >> 16); 54
55 if(TEMP_DATA >= 450) 56 { 57 //正溫度
58 TEMP_DATA -= 450; 59 Cnt = TEMP_DATA%10; 60 TEMP_DATA = TEMP_DATA/10; 61 printf("采集到的溫度度值是:%d.%d\r\n",TEMP_DATA,Cnt); 62 } 63 else
64 { 65 //負溫度
66 TEMP_DATA = 450 - TEMP_DATA; 67 Cnt = TEMP_DATA%10; 68 TEMP_DATA = TEMP_DATA/10; 69 printf("采集到的溫度度值是:-%d.%d\r\n",TEMP_DATA,Cnt); 70 } 71 } 72
73 Cnt = SHTC3_CRC_CHECK(HUM_MEASUREMENT,Hum_Check_Num); 74 if(Cnt == 0) 75 { 76 result = HUM_MEASUREMENT*100; 77 HUM_DATA = (uint8_t)(result >> 16); 78
79 printf("采集到的濕度值是:%d%%\r\n",HUM_DATA); 80 } 81 printf("\r\n"); 82 } 83 } 84
85 SHTC3_INTO_SLEEP(); 86 } 87 }
完整的工程代碼可以在:https://github.com/h1019384803/STM32F103ZET6_I2C查看。