STM32使用HAL库编写SHT2x温湿度传感器驱动
??????? 溫濕度傳感器在嵌入式開發中應用場景非常多。本文主要利用STM32及HAL庫完成SHT2x溫濕度傳感器溫濕度值得讀取及將值通過串口打印出來。
一、SHT20芯片芯片介紹
1、官方收據手冊可以該網站下載:數字溫濕度傳感器 SHT2X-深圳市森思德克科技有限公司
該網站提供的手冊為英文的,該芯片使用較多,通過百度也能找到中文的。
2、SHT20 配有一個全新設計的 CMOSens?芯片、一 個經過改進的電容式濕度傳感元件和一個標準的能 隙溫度傳感元件。(這段摘自數據手冊)
二、芯片技術手冊讀到可能對后續編程有用的信息
1、該芯片采用數字輸出,I2C接口,低功耗。
2、SHT20的分辨率可以通過輸入命令進行改變(8/12bit乃至12/14bit的RH/T)。RH代表濕度,T代表溫度。
3、默認測量分辨率14bit(溫度)/12bit(濕度),可通過寄存器發送命令將其減少到12/8bit,11/11bit,13/10bit。
4、溫濕度測量頻率過高,傳感器自身溫度會升高而影響精度。
5、接口定義
6、傳感器通訊流程如下
(1)啟動傳感器:將傳感器上電后,傳感器最多需要15毫秒時間(此時SCL為高電平)以達到空閑狀態,即做好準備接收由主機MCU發送的命令。
(2)啟動/停止時序:參照標準I2C總線。
(3)在啟動傳輸后,隨后傳輸的I2C首字節應包括7位的I2C設備地址和一個SDA方向位(讀:1,寫:0)。等待應答后,發送溫度或濕度的測量命令。
(4)傳感器地址由廠商寫死的,I2C 設備地址( 地址‘1000’000’)和一個 SDA
 方向位(讀 R: ‘1’,寫 W: ‘0’)。
7、基本命令集
| 命令 | 釋義 | 代碼 | 十六進制 | 
| 觸發 T 測量 | 保持主機 | 1110’0011 | 0XE3(主機模式) | 
| 觸發 RH 測量 | 保持主機 | 1110’0101 | 0XE5(主機模式) | 
| 觸發 T 測量 | 非保持主機 | 1111’0011 | 0XF3(非主機模式) | 
| 觸發 RH 測量 | 非保持主機 | 1111’0101 | 0XF5(非主機模式) | 
| 寫用戶寄存器 | 1110’0110 | 0XE6 | |
| 讀用戶寄存器 | 1110’0111 | 0XE7 | |
| 軟復位 | 1111’1110 | 0XFE | 
8、主機/非主機模式
(1)MCU與傳感器之間的通訊有兩種不同的工作方式:主機模式或非主機模式。
(2)在主機模式下,在測量過程中,SCL線被封鎖(由傳感器進行控制)。在非主機模式下,當傳感器執行測量任務時,SCL線仍然保持開放狀態,可進行其他通訊。非主機模式允許傳感器進行測量時在總線上處理其他I2C總線通訊任務。
(3)在主機模式測量時,SHT2x將SCL拉低強制主機進入等待狀態。通過釋放SCL線,表示傳感器內部處理工作結束,進而可以繼續數據傳送。
第一步:發送起始信號→
第二步:發送傳感器寫地址→
第三步驟:等待傳感器應答→
第四步:發送測量信號命令→
第五步驟:等待傳感器應答→
第六步:發送起始信號→
第七步:發送傳感器讀地址→
第八步:等待傳感器應答→
第九步:測量期間保持(延時一會)→
第十步:接收數據高八位,主機發送應答→
第十一步:接收數據低八位,主機發送應答→
第十二步:接收校驗碼值→主機發送NACK、P(傳輸停止時序)。
由于測量的最大分辨率為14位,第二字節SDA上的后兩位(bit43和bit44)用來傳輸相關的狀態信息。
后兩位即LSB Stat簡稱 LSBs 。兩個LSBs中的bit1表明測量的類型('0':溫度, '1':濕度)。bit0位當前沒有賦值。(這點非主機模式也是這種)
(4)在非主機模式時,MCU需要對傳感器狀態進行查詢。主機發送一個啟動傳輸時序,之后發送讀地址( 1000’0001)。如果內部處理工作完成,單片機查詢到傳感器發出的確認信號后,相關的數據就可以通過MCU進行讀取。如果測量處理工作沒有完成,傳感器無確認位(ACK)輸出,此時必須重新發送啟動傳輸時序。
?9、軟復位
三、I2C代碼
1、頭文件
#ifndef __DRV_SHT2x_I2C_H #define __DRV_SHT2x_I2C_H/*頭文件包含*/ #include "drv_gpio.h" #include "drv_i2c.h" /*包含uS級延時函數*//*宏定義*/ /*置位與清零SCL管腳*/ #define __SHT2X_I2C_SCL_H() HAL_GPIO_WritePin(SHT_SCL_GPIO_Port,SHT_SCL_Pin,GPIO_PIN_SET) #define __SHT2X_I2C_SCL_L() HAL_GPIO_WritePin(SHT_SCL_GPIO_Port,SHT_SCL_Pin,GPIO_PIN_RESET) /*置位與清零SDA管腳*/ #define __SHT2X_I2C_SDA_H() HAL_GPIO_WritePin(SHT_SDA_GPIO_Port,SHT_SDA_Pin,GPIO_PIN_SET) #define __SHT2X_I2C_SDA_L() HAL_GPIO_WritePin(SHT_SDA_GPIO_Port,SHT_SDA_Pin,GPIO_PIN_RESET) /*讀取SDA管腳狀態*/ #define __SHT2X_READ_I2C_SDA() HAL_GPIO_ReadPin(SHT_SDA_GPIO_Port,SHT_SDA_Pin) /*讀取SCL管腳狀態*/ #define __SHT2X_READ_I2C_SCL() HAL_GPIO_ReadPin(SHT_SCL_GPIO_Port,SHT_SCL_Pin)/*設置SDA管腳為輸出模式*/ #define __SHT2X_I2C_SDA_OUT() SHT_SDA_OutputMode() /*設置SDA管腳為輸入模式*/ #define __SHT2X_I2C_SDA_INPUT() SHT_SDA_InputMode()/*函數聲明*/ void SHT_SDA_OutputMode(); /*設置SHT_SDA管腳為輸出模式*/ void SHT_SDA_InputMode(void); /*設置SHT_SDA管腳為輸入模式*/ void SHT2X_I2C_Init(void); /*SHT_SDA和SHT_SCL引腳電平初始化*/ void SHT2X_I2C_Start(void); /*sht2x_I2C總線起始信號時序*/ void SHT2X_I2C_Stop(void); /*sht2x_I2C總線停止信號時序*/ uint8_t SHT2X_I2C_Wait_Ack(void); /*IIC等待應答信號,1接收應答失敗,0接收應答成功*/ void SHT2X_I2C_Ack(void); /*IIC產生應答*/ void SHT2X_I2C_NAck(void); /*IIC不產生應答*/ void SHT2X_I2C_Write_Byte(uint8_t Byte); /*SHT2X_I2C總線寫字節時序*/ uint8_t SHT2X_I2C_Read_Byte(I2C_ACK_TypeDef AckValue); /*SHT2X_I2C總線讀字節時序*/#endif2、C文件
#include "drv_sht2x_i2c.h"/**功能:設置SHT_SDA管腳為輸出模式*參數:無*返回值:無*/ void SHT_SDA_OutputMode() {GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = SHT_SDA_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; /*輸出模式*/GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); }/**功能:設置SHT_SDA管腳為輸入模式*參數:無*返回值:無*/ void SHT_SDA_InputMode(void) {GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = SHT_SDA_Pin; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; /*輸入模式*/GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); }/**功能:SHT_SDA和SHT_SCL引腳電平初始化*參數:無*返回值:無*測試:OK*/ void SHT2X_I2C_Init(void) {__SHT2X_I2C_SCL_H();__SHT2X_I2C_SDA_H();HAL_Delay(15); /*延時15mS*/ }/**功能:sht2x_I2C總線起始信號時序*參數:無*返回值:無*注意:開始狀態是由主機控制的一種特殊總線狀態,指示從機傳輸開始(Start之后,BUS總線一般被認為處于占線狀態)*/ void SHT2X_I2C_Start(void) {__SHT2X_I2C_SDA_OUT(); /*SDA配置為輸出模式*//*SCL為高電平,SDA的下降沿為I2C起始信號*/__SHT2X_I2C_SDA_H();__SHT2X_I2C_SCL_H();I2C_Delay_us(20);__SHT2X_I2C_SDA_L();I2C_Delay_us(20);__SHT2X_I2C_SCL_L(); }/**功能:sht2x_I2C總線停止信號時序*參數:無*返回值:無*注意:停止狀態是由主機控制的一種特殊的總線狀態,指示從機傳輸結束(Stop之后,BUS總線一般被認為處于空閑狀態)*/ void SHT2X_I2C_Stop(void) {__SHT2X_I2C_SDA_OUT();/*SCL為高電平,SDA的上升沿為I2C停止信號*/__SHT2X_I2C_SDA_L();__SHT2X_I2C_SCL_H();I2C_Delay_us(1);I2C_Delay_us(10);__SHT2X_I2C_SDA_H(); }/**功能:IIC等待應答信號*參數:無*返回值:1接收應答失敗,0接收應答成功*/ uint8_t SHT2X_I2C_Wait_Ack(void) {uint8_t ucErrTime = 0;SHT_SDA_InputMode(); __SHT2X_I2C_SDA_H();I2C_Delay_us(10);__SHT2X_I2C_SCL_H();I2C_Delay_us(10);while(__SHT2X_READ_I2C_SDA()){ucErrTime++;if(ucErrTime > 250){SHT2X_I2C_Stop();return NACK;}}__SHT2X_I2C_SCL_L(); return ACK; }/**功能:IIC產生應答*/ void SHT2X_I2C_Ack(void) {__SHT2X_I2C_SCL_L();__SHT2X_I2C_SDA_OUT();__SHT2X_I2C_SDA_L();I2C_Delay_us(20);__SHT2X_I2C_SCL_H();I2C_Delay_us(20);__SHT2X_I2C_SCL_L(); }/**功能:IIC不產生應答*/ void SHT2X_I2C_NAck(void) {__SHT2X_I2C_SCL_L();__SHT2X_I2C_SDA_OUT();__SHT2X_I2C_SDA_H();I2C_Delay_us(20);__SHT2X_I2C_SCL_H();I2C_Delay_us(20);__SHT2X_I2C_SCL_L(); }/**功能:SHT2X_I2C總線寫字節時序*參數:Byte:寫入的內容*測試:OK*/ void SHT2X_I2C_Write_Byte(uint8_t Byte) {__SHT2X_I2C_SDA_OUT(); /*SDA配置為輸出模式*//*SCL為低電平時,SDA準備數據,接著SCL為高電平,讀取SDA數據*/for (uint8_t i = 0; i < 8; i++){/*SCL清零,主機SDA準備數據*/__SHT2X_I2C_SCL_L();I2C_Delay_us(1);if((Byte & (1 << 7)) == (1 << 7)){__SHT2X_I2C_SDA_H();}else{__SHT2X_I2C_SDA_L();}I2C_Delay_us(1);/*SCL置高,傳輸數據*/__SHT2X_I2C_SCL_H();I2C_Delay_us(10);/*準備發送下一比特位*/Byte <<= 1;}__SHT2X_I2C_SCL_L(); }/**功能:SHT2X_I2C總線讀字節時序*參數:*返回值:讀取到的數據*測試:OK*/ uint8_t SHT2X_I2C_Read_Byte(I2C_ACK_TypeDef AckValue) {uint8_t byte = 0;__SHT2X_I2C_SDA_INPUT();/*SCL為低電平時,SDA準備數據,接著SCL為高電平,讀取SDA數據*/for (uint8_t i = 0; i < 8; i++){/*準備接收下一比特位*/byte <<= 1;/*SCL清零,從機SDA準備數據*/__SHT2X_I2C_SCL_L();I2C_Delay_us(10);/*SCL置高,獲取數據*/__SHT2X_I2C_SCL_H();I2C_Delay_us(10); byte |= __SHT2X_READ_I2C_SDA(); }/*SCL清零,主機準備應答信號*/__SHT2X_I2C_SCL_L();I2C_Delay_us(1);__SHT2X_I2C_SDA_OUT();/*主機發送應答信號*/ if(AckValue == ACK){__SHT2X_I2C_SDA_L();}else{__SHT2X_I2C_SDA_H(); }I2C_Delay_us(1);__SHT2X_I2C_SCL_H(); I2C_Delay_us(10);/*SCL先清零,再釋放SDA,防止連續傳輸數據時,從機錯將SDA釋放信號當成NACk信號*/__SHT2X_I2C_SCL_L();__SHT2X_I2C_SDA_H(); I2C_Delay_us(1);/*返回數據*/return byte; }四、SHT2x代碼
1、頭文件
#ifndef __SHT2_H #define __SHT2_H/*頭文件包含*/ #include "main.h"/*宏定義*/ #define SHT2x_ADDR_READ 0x81 /*傳感器i2C讀地址*/ #define SHT2x_ADDR_WRITE 0x80 /*傳感器I2C寫地址*//*測量信號的選擇*/ typedef enum{HUMIDITY, /*選擇濕度*/TEMP /*選擇溫度*/ }etSHT2xMeasureType; /* *功能:傳感器命令 *TRIG:觸發(trigger) *MEASUREMENT:測量*HM:hold master*/ typedef enum{/*主機模式*/TRIG_T_MEASUREMENT_HM = 0xE3, /*觸發溫度測量,主機模式*/TRIG_RH_MEASUREMENT_HM = 0xE5, /*觸發濕度測量,主機模式*//*非主機模式*/TRIG_T_MEASUREMENT_POLL = 0xF3, /*觸發溫度測量,非保持主機*/TRIG_RH_MEASUREMENT_POLL = 0xF5, /*觸發濕度測量,非保持主機*/USER_REG_W = 0xE6, /*command writing user register(寫用戶寄存器)*/USER_REG_R = 0xE7, /*command reading user register(讀用戶寄存器)*/SOFT_RESET = 0xFE /*command soft reset(軟件復位)*/ }etSHT2xCommand;/*函數聲明*/ float SHT2x_MeasurePoll(etSHT2xMeasureType SHT2xMeasureType); /*非主機模式采集溫度或濕度*/#endif2、C文件
/**文件:SHT2x.c *功能:溫濕度采集程序*//*頭文件包含*/ #include "SHT2x.h" #include "drv_uart.h" #include "drv_sht2x_i2c.h"/**功能:非主機模式采集溫度或濕度*參數:SHT2xMeasureType:需要采集的項,HUMIDITY濕度 TEMP溫度*返回值:讀到的溫濕度值 */ float SHT2x_MeasurePoll(etSHT2xMeasureType SHT2xMeasureType) {float temp; /*臨時變量*/unsigned char MSB,LSB; /*存儲測量值的高八位和低八位*/float Humidity,Temperature;SHT2X_I2C_Start(); /*sht2x_I2C總線起始信號時序*/SHT2X_I2C_Write_Byte(SHT2x_ADDR_WRITE); /*sht2x_I2C總線寫傳感器寫地址*/if(SHT2X_I2C_Wait_Ack() == ACK) /*寫寫地址等待應答*/ {switch(SHT2xMeasureType) { case HUMIDITY: /*濕度*/ SHT2X_I2C_Write_Byte(TRIG_RH_MEASUREMENT_POLL); /*非主機模式測濕度命令*/ break; case TEMP: /*溫度*/ SHT2X_I2C_Write_Byte(TRIG_T_MEASUREMENT_POLL); /*非主機模式測溫度命令*/break; default: printf("Tip: SHT2x_MeasurePoll function error.\r\n");break;}if(SHT2X_I2C_Wait_Ack() == 0) /*非主機模式測溫濕度指令應答*/ {HAL_Delay(85); /*延時等待測量完成*/SHT2X_I2C_Start(); SHT2X_I2C_Write_Byte(SHT2x_ADDR_READ); /*sht2x_I2C總線寫傳感器讀地址*/if(SHT2X_I2C_Wait_Ack() == 0) /*寫讀地址等待應答*/{MSB = SHT2X_I2C_Read_Byte(ACK);LSB = SHT2X_I2C_Read_Byte(ACK);SHT2X_I2C_Read_Byte(NACK); SHT2X_I2C_Stop();LSB &= 0xfc;temp = MSB*256 + LSB;if (SHT2xMeasureType == HUMIDITY){ Humidity =(temp*125)/65536-6;//printf("Humidity = %.2f\r\n",Humidity);return Humidity;} else { Temperature = (temp*175.72)/65536-46.85;//printf("Temperature = %.2f\r\n",Temperature);return Temperature; }}}}printf("Tip: SHT2x_MeasurePoll error\r\n");return 0XFF; /*表示出錯了*/}五、測試
float Humidity,Temperature; //定義溫度和濕度變量 while (1){/*Test*/Temperature = SHT2x_MeasurePoll(TEMP); /*非主機模式采集溫度*/printf("Temperature%.2f\r\n",Temperature);Humidity = SHT2x_MeasurePoll(HUMIDITY); /*非主機模式采集濕度*/printf("Humidity = %.2f\r\n",Humidity);HAL_Delay(1000); }總結
以上是生活随笔為你收集整理的STM32使用HAL库编写SHT2x温湿度传感器驱动的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: php 带参页面跳转页面,跳转页面带参数
- 下一篇: Android基础知识精简版(转)
