由瑞士Sensirion推出的 SHT20數(shù)字溫濕度傳感器,基于領(lǐng)先世界的CMOSens ? 數(shù)字傳感技術(shù),具有極高的可靠性和卓越的長(zhǎng)期穩(wěn)定性。全量程標(biāo)定,兩線數(shù)字接口,可與單片機(jī)直接相連,大大縮短研發(fā)時(shí)間、簡(jiǎn)化外圍電路并降低費(fèi)用。此外,體積微小、響應(yīng)迅速、低能耗、可浸沒(méi)、抗干擾能力強(qiáng)、溫濕一體,兼有露點(diǎn)測(cè)量,性價(jià)比高,使該產(chǎn)品能夠適于多種場(chǎng)合的應(yīng)用。
一模塊來(lái)源
資料下載鏈接:https://pan.baidu.com/s/1HrQkwECvGgQSHvt_RNdLdA
二 規(guī)格參數(shù)
工作電壓:2.1~3.6V
工作電流:0.1~1000uA
溫度精度:±0.3℃
溫度范圍:-40~125℃
濕度范圍:0~100 %RH
濕度精度:±3%RH
輸出方式: IIC
管腳數(shù)量:4 Pin
以上信息見(jiàn)廠家資料文件
三移植過(guò)程
我們的目標(biāo)是將例程移植至CW32F030C8T6開(kāi)發(fā)板上【能夠測(cè)量環(huán)境溫濕度】。首先要獲取資料,查看數(shù)據(jù)手冊(cè)應(yīng)如何實(shí)現(xiàn)讀取數(shù)據(jù),再移植至我們的工程。
3.1查看資料
開(kāi)始傳輸后,隨后先傳輸首字節(jié)包括I2C設(shè)備地址(7bit)和一個(gè)SDA方向位(R:1, W:0)。
一個(gè)時(shí)鐘發(fā)送一個(gè)位,在第8個(gè)下降沿之后,通過(guò)拉低SDA引腳(ACK位 為0),只是傳感器數(shù)據(jù)接收正常。在發(fā)出測(cè)量命令之后(‘1110’‘0011’代表溫度測(cè)量,‘1110’‘0101’代表相對(duì)濕度測(cè)量 ,這種為主機(jī)模式),MCU必須等待測(cè)量完成。
主機(jī)模式:
測(cè)量過(guò)程中,SCL線被封鎖(由傳感器控制),在測(cè)量時(shí),SHT2x將SCL拉低強(qiáng)制主機(jī)進(jìn)入等待狀態(tài)。當(dāng)釋放SCL線,表示傳感器內(nèi)部工作接收,可以繼續(xù)進(jìn)行數(shù)據(jù)傳送
灰色的部分是傳感器控制的,當(dāng)傳感器給MCU返回?cái)?shù)據(jù)時(shí),每返回一個(gè)字節(jié),MCU要返回一個(gè)ACK信號(hào),當(dāng)接收完畢之后,返回一個(gè)NACK并接著傳輸停止時(shí)序(P)。
注:校驗(yàn)和可以不需要,不需要?jiǎng)t就在數(shù)據(jù)接收完之后返回NACK
非主機(jī)模式:
測(cè)量過(guò)程中,SCL線是開(kāi)發(fā)狀態(tài),可進(jìn)行其他通信,可以在總線上處理其他I2C總線通信任務(wù)。
當(dāng)MCU要對(duì)傳感器狀態(tài)進(jìn)行查詢時(shí),先發(fā)起一個(gè)開(kāi)始信號(hào),在發(fā)送從機(jī)地址和SDA方向位(寫(xiě)),此時(shí)從機(jī)匹配地址成功,則發(fā)送ACK信號(hào),并開(kāi)始測(cè)量。如果傳感器完成了測(cè)量過(guò)程,并且發(fā)送ASK信號(hào),那么MCU就可以讀取相關(guān)數(shù)據(jù)。如果測(cè)量沒(méi)有完成,傳感器發(fā)送NACK信號(hào),此時(shí)MCU必須重新發(fā)送啟動(dòng)傳輸時(shí)序,直至測(cè)量完成,MCU讀取數(shù)據(jù)。
注意:測(cè)量的數(shù)據(jù),溫度和濕度均為兩個(gè)字節(jié)。而且無(wú)論哪一種傳輸模式,測(cè)量的最大分辨率最大是14bit,數(shù)據(jù)的第二個(gè)字節(jié)SDA上最后兩位是用來(lái)標(biāo)記相關(guān)狀態(tài)信息。其中bit1表示測(cè)量類(lèi)型(0是溫度,1是濕度)
灰色的區(qū)域是傳感器控制的,如果不需要校驗(yàn)和,那么在接收完兩個(gè)字節(jié)的數(shù)據(jù)之后就MCU直接發(fā)出NACK信號(hào)再接著發(fā)出停止時(shí)序(P),則結(jié)束通信。
通常測(cè)量的最長(zhǎng)時(shí)間取決于測(cè)量類(lèi)型和分辨率.
在計(jì)算MCU通信時(shí)間時(shí),測(cè)量溫度選擇最長(zhǎng)測(cè)量時(shí)間是85ms,而測(cè)量相對(duì)濕度選擇最長(zhǎng)的時(shí)間是29ms。
傳感器內(nèi)部設(shè)置的默認(rèn)分辨率為相對(duì)濕度12位和溫度14位。SDA的輸出數(shù)據(jù)被轉(zhuǎn)換成兩個(gè)字節(jié)的數(shù)據(jù)包,高字節(jié)MSB在前(左對(duì)齊)。每個(gè)字節(jié)后面都跟隨一個(gè)應(yīng)答位。兩個(gè)狀態(tài)位,即 LSB的后兩位在進(jìn)行物理計(jì)算前須置0。計(jì)算濕度:其中SRH表示我們讀取到的濕度原始數(shù)據(jù)。
計(jì)算溫度:其中ST表示我們讀取到的溫度原始數(shù)據(jù)。
3.2引腳選擇
模塊接線圖
3.3移植至工程
移植步驟中的導(dǎo)入.c和.h文件與【CW32模塊使用】DHT11溫濕度傳感器相同,
只是將.c和.h文件更改為bsp_sht20.c與bsp_sht20.h。這里不再過(guò)多講述,移植完成后面修改相關(guān)代碼。
在文件bsp_sht20.c中,編寫(xiě)如下代碼。
/*
* Change Logs:
* Date Author Notes
* 2024-06-20 LCKFB-LP first version
*/
#include "bsp_sht20.h"
#include "board.h"
#include "stdio.h"
void SHT20_GPIO_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStruct; // GPIO初始化結(jié)構(gòu)體
RCC_SHT20_ENABLE(); // 使能GPIO時(shí)鐘
GPIO_InitStruct.Pins = GPIO_SDA|GPIO_SCL; // GPIO引腳
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // 開(kāi)漏輸出
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; // 輸出速度高
GPIO_Init(PORT_SHT20, &GPIO_InitStruct); // 初始化
}
/******************************************************************
* 函 數(shù) 名 稱:IIC_Start
* 函 數(shù) 說(shuō) 明:IIC起始信號(hào)
* 函 數(shù) 形 參:無(wú)
* 函 數(shù) 返 回:無(wú)
* 作 者:LC
* 備 注:無(wú)
******************************************************************/
void IIC_Start(void)
{
SDA_OUT();
SCL(0);
SDA(1);
SCL(1);
delay_us(5);
SDA(0);
delay_us(5);
SCL(0);
delay_us(5);
}
/******************************************************************
* 函 數(shù) 名 稱:IIC_Stop
* 函 數(shù) 說(shuō) 明:IIC停止信號(hào)
* 函 數(shù) 形 參:無(wú)
* 函 數(shù) 返 回:無(wú)
* 作 者:LC
* 備 注:無(wú)
******************************************************************/
void IIC_Stop(void)
{
SDA_OUT();
SCL(0);
SDA(0);
SCL(1);
delay_us(5);
SDA(1);
delay_us(5);
}
/******************************************************************
* 函 數(shù) 名 稱:IIC_Send_Ack
* 函 數(shù) 說(shuō) 明:主機(jī)發(fā)送應(yīng)答
* 函 數(shù) 形 參:0應(yīng)答 1非應(yīng)答
* 函 數(shù) 返 回:無(wú)
* 作 者:LC
* 備 注:無(wú)
******************************************************************/
void IIC_Send_Ack(uint8_t ack)
{
SDA_OUT();
SCL(0);
SDA(0);
delay_us(5);
if(!ack) SDA(0);
else SDA(1);
SCL(1);
delay_us(5);
SCL(0);
SDA(1);
}
/******************************************************************
* 函 數(shù) 名 稱:IIC_Wait_Ack
* 函 數(shù) 說(shuō) 明:等待從機(jī)應(yīng)答
* 函 數(shù) 形 參:無(wú)
* 函 數(shù) 返 回:1=無(wú)應(yīng)答 0=有應(yīng)答
* 作 者:LC
* 備 注:無(wú)
******************************************************************/
uint8_t IIC_Wait_Ack(void)
{
char ack = 0;
unsigned char ack_flag = 10;
SDA_IN();
SDA(1);
delay_us(5);
SCL(1);
delay_us(5);
while( (SDA_GET()==1) && ( ack_flag ) )
{
ack_flag--;
delay_us(5);
}
if( ack_flag <= 0 )
{
IIC_Stop();
return 1;
}
else
{
SCL(0);
SDA_OUT();
}
return ack;
}
/******************************************************************
* 函 數(shù) 名 稱:IIC_Write
* 函 數(shù) 說(shuō) 明:IIC寫(xiě)一個(gè)字節(jié)
* 函 數(shù) 形 參:dat寫(xiě)入的數(shù)據(jù)
* 函 數(shù) 返 回:無(wú)
* 作 者:LC
* 備 注:無(wú)
******************************************************************/
void IIC_Write(uint8_t data)
{
int i = 0;
SDA_OUT();
SCL(0);//拉低時(shí)鐘開(kāi)始數(shù)據(jù)傳輸
for( i = 0; i < 8; i++ )
{
SDA( (data & 0x80) >> 7 );
delay_us(2);
data<<=1;
delay_us(6);
SCL(1);
delay_us(4);
SCL(0);
delay_us(4);
}
}
/******************************************************************
* 函 數(shù) 名 稱:IIC_Read
* 函 數(shù) 說(shuō) 明:IIC讀1個(gè)字節(jié)
* 函 數(shù) 形 參:無(wú)
* 函 數(shù) 返 回:讀出的1個(gè)字節(jié)數(shù)據(jù)
* 作 者:LC
* 備 注:無(wú)
******************************************************************/
uint8_t IIC_Read(void)
{
unsigned char i,receive=0;
SDA_IN();//SDA設(shè)置為輸入
for(i=0;i<8;i++ )
{
SCL(0);
delay_us(5);
SCL(1);
delay_us(5);
receive<<=1;
if( SDA_GET() )
{
receive|=1;
}
delay_us(5);
}
return receive;
}
/******************************************************************
* 函 數(shù) 名 稱:SHT20_Read
* 函 數(shù) 說(shuō) 明:測(cè)量溫濕度
* 函 數(shù) 形 參:regaddr寄存器地址 regaddr=0xE3測(cè)量溫度 =0xE5測(cè)量濕度
* 函 數(shù) 返 回:regaddr=0xE3時(shí)返回溫度,regaddr=0xE5時(shí)返回濕度
* 作 者:LC
* 備 注:無(wú)
******************************************************************/
float SHT20_Read(uint8_t regaddr)
{
unsigned char data_H = 0;
unsigned char data_L = 0;
float temp = 0;
IIC_Start();
IIC_Write(0x80|0);
if( IIC_Wait_Ack() == 1 ) printf("error -1rn");
IIC_Write(regaddr);
if( IIC_Wait_Ack() == 1 ) printf("error -2rn");
do{
delay_us(10);
IIC_Start();
IIC_Write(0x80|1);
}while( IIC_Wait_Ack() == 1 );
delay_us(20);
data_H = IIC_Read();
IIC_Send_Ack(0);
data_L = IIC_Read();
IIC_Send_Ack(1);
IIC_Stop();
if( regaddr == 0xf3 )
{
temp = ((data_H<<8)|data_L) / 65536.0 * 175.72 - 46.85;
}
if( regaddr == 0xf5 )
{
temp = ((data_H<<8)|data_L) / 65536.0 * 125.0 - 6;
}
return temp;
}
在文件bsp_sht20.h中,編寫(xiě)如下代碼。
/*
* Change Logs:
* Date Author Notes
* 2024-06-20 LCKFB-LP first version
*/
#ifndef __BSP_SHT20_H__
#define __BSP_SHT20_H__
#include "board.h"
//端口移植
#define RCC_SHT20_ENABLE() __RCC_GPIOB_CLK_ENABLE()
#define PORT_SHT20 CW_GPIOB
#define GPIO_SDA GPIO_PIN_9
#define GPIO_SCL GPIO_PIN_8
//設(shè)置SDA輸出模式
#define SDA_OUT() {
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pins = GPIO_SDA;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_Init(PORT_SHT20, &GPIO_InitStruct);
}
//設(shè)置SDA輸入模式
#define SDA_IN() {
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pins = GPIO_SDA;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_Init(PORT_SHT20, &GPIO_InitStruct);
}
//獲取SDA引腳的電平變化
#define SDA_GET() GPIO_ReadPin(PORT_SHT20, GPIO_SDA)
//SDA與SCL輸出
#define SDA(x) GPIO_WritePin(PORT_SHT20, GPIO_SDA, (x?GPIO_Pin_SET:GPIO_Pin_RESET) )
#define SCL(x) GPIO_WritePin(PORT_SHT20, GPIO_SCL, (x?GPIO_Pin_SET:GPIO_Pin_RESET) )
void SHT20_GPIO_INIT(void);
float SHT20_Read(unsigned char regaddr);
#endif
四移植驗(yàn)證
在自己工程中的main主函數(shù)中,編寫(xiě)如下。
/*
* Change Logs:
* Date Author Notes
* 2024-06-20 LCKFB-LP first version
*/
#include "board.h"
#include "stdio.h"
#include "bsp_uart.h"
#include "bsp_sht20.h"
#define T_ADDR 0xf3 // 溫度
#define PH_ADDR 0xf5 // 濕度
int32_t main(void)
{
board_init(); // 開(kāi)發(fā)板初始化
uart1_init(115200); // 串口1波特率115200
SHT20_GPIO_INIT();
delay_ms(1000);
printf("SHT20 Start!!rn");
while(1)
{
printf("溫度 = %.2f ℃rn", SHT20_Read(T_ADDR) );
printf("濕度 = %.2f %%RHrn",SHT20_Read(PH_ADDR) );
printf("n");
delay_ms(1000);
}
}
上電現(xiàn)象:
模塊移植成功案例代碼:
鏈接:https://pan.baidu.com/s/13EW713tzDGwSDVUw--ouJQ?pwd=LCKF
提取碼:LCKF