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