SHT20 温湿度传感器
由瑞士 Sensirion 推出的 SHT20 数字温湿度传感器,基于领先世界的 CMOSens ® 数字传感技术,具有极高的可靠性和卓越的长期稳定性。全量程标定,两线数字接口,可与单片机直接相连,大大缩短研发时间、简化外围电路并降低费用。此外,体积微小、响应迅速、低能耗、可浸没、抗干扰能力强、温湿一体,兼有露点测量,性价比高,使该产品能够适于多种场合的应用。
模块来源
采购链接:
SHT20 温湿度传感器模块/数字型温湿度测量模块 I2C 通讯小体积模块
资料下载链接:
https://pan.baidu.com/s/1HrQkwECvGgQSHvt_RNdLdA
规格参数
工作电压: 2.1~3.6V
工作电流: 0.1~1000uA
温度精度: ±0.3℃
温度范围: -40~125℃
湿度范围: 0~100 %RH
湿度精度: ±3%RH
输出方式: IIC
管脚数量:4 Pin
移植过程
我们的目标是在天空星 STM32F407 上能够测量环境温湿。首先要获取资料,查看数据手册应如何实现,再移植至我们的工程。
查看资料
开始传输后,随后先传输首字节包括 I2C 设备地址(7bit)和一个 SDA 方向位(R:1, W:0)。
一个时钟发送一个位,在第 8 个下降沿之后,通过拉低 SDA 引脚(ACK 位 为 0),只是传感器数据接收正常。在发出测量命令之后(‘1110’‘0011’代表温度测量,‘1110’‘0101’代表相对湿度测量 ,这种为主机模式),MCU 必须等待测量完成。
灰色的部分是传感器控制的,当传感器给 MCU 返回数据时,每返回一个字节,MCU 要返回一个 ACK 信号,当接收完毕之后,返回一个 NACK 并接着传输停止时序(P)。
注:校验和可以不需要,不需要则就在数据接收完之后返回 NACK
② 非主机模式:测量过程中,SCL 线是开发状态,可进行其它通信,可以在总线上处理其它 I2C 总线通信任务。
当 MCU 要对传感器状态进行查询时,先发起一个开始信号,在发送从机地址和 SDA 方向位(写),此时从机匹配地址成功,则发送 ACK 信号,并开始测量。如果传感器完成了测量过程,并且发送 ASK 信号,那么 MCU 就可以读取相关数据。如果测量没有完成,传感器发送 NACK 信号,此时 MCU 必须重新发送启动传输时序,直至测量完成,MCU 读取数据。
注意:测量的数据,温度和湿度均为两个字节。而且无论哪一种传输模式,测量的最大分辨率最大是 14bit,数据的第二个字节 SDA 上最后两位是用来标记相关状态信息。其中 bit1 表示测量类型(0 是温度,1 是湿度)
灰色的区域是传感器控制的,如果不需要校验和,那么在接收完两个字节的数据之后就 MCU 直接发出 NACK 信号再接着发出停止时序(P),则结束通信。
通常测量的最长时间取决于测量类型和分辨率.
在计算 MCU 通信时间时,测量温度选择最长测量时间是 85ms,而测量相对湿度选择最长的时间是 29ms。
传感器内部设置的默认分辨率为相对湿度 12 位和温度 14 位。SDA 的输出数据被转换成两个字节的数据包,高字节 MSB 在前(左对齐)。每个字节后面都跟随一个应答位。两个状态位,即 LSB 的后两位在进行物理计算前须置 0。
计算湿度:其中 SRH 表示我们读取到的湿度原始数据。
计算温度:其中 ST 表示我们读取到的温度原始数据。
引脚选择
移植至工程
移植步骤中的导入.c 和.h 文件与第二章的第 1 小节【DHT11 温湿度传感器】相同,只是将.c 和.h 文件更改为 bsp_sht20.c 与 bsp_sht20.h。这里不再过多讲述,移植完成后面修改相关代码。
在文件 bsp_sht20.c 中,编写如下代码。
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:https://oshwhub.com/forum
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*
Change Logs:
* Date Author Notes
* 2024-03-19 LCKFB-LP first version
*/
#include "bsp_sht20.h"
#include "board.h"
#include "stdio.h"
void SHT20_GPIO_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_SHT20, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_SDA|GPIO_SCL;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(PORT_SHT20, &GPIO_InitStructure);
GPIO_SetBits(PORT_SHT20, GPIO_SDA|GPIO_SCL);
}
/******************************************************************
* 函 数 名 称:IIC_Start
* 函 数 说 明:IIC起始信号
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
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);
}
/******************************************************************
* 函 数 名 称:IIC_Stop
* 函 数 说 明:IIC停止信号
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void IIC_Stop(void)
{
SDA_OUT();
SCL(0);
SDA(0);
SCL(1);
delay_us(5);
SDA(1);
delay_us(5);
}
/******************************************************************
* 函 数 名 称:IIC_Send_Ack
* 函 数 说 明:主机发送应答
* 函 数 形 参:0应答 1非应答
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
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);
}
/******************************************************************
* 函 数 名 称:IIC_Wait_Ack
* 函 数 说 明:等待从机应答
* 函 数 形 参:无
* 函 数 返 回:1=无应答 0=有应答
* 作 者:LC
* 备 注:无
******************************************************************/
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;
}
/******************************************************************
* 函 数 名 称:IIC_Write
* 函 数 说 明:IIC写一个字节
* 函 数 形 参:dat写入的数据
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void IIC_Write(uint8_t data)
{
int i = 0;
SDA_OUT();
SCL(0);//拉低时钟开始数据传输
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);
}
}
/******************************************************************
* 函 数 名 称:IIC_Read
* 函 数 说 明:IIC读1个字节
* 函 数 形 参:无
* 函 数 返 回:读出的1个字节数据
* 作 者:LC
* 备 注:无
******************************************************************/
uint8_t IIC_Read(void)
{
unsigned char i,receive=0;
SDA_IN();//SDA设置为输入
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;
}
/******************************************************************
* 函 数 名 称:SHT20_Read
* 函 数 说 明:测量温湿度
* 函 数 形 参:regaddr寄存器地址 regaddr=0xE3测量温度 =0xE5测量湿度
* 函 数 返 回:regaddr=0xE3时返回温度,regaddr=0xE5时返回湿度
* 作 者:LC
* 备 注:无
******************************************************************/
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 -1\r\n");
IIC_Write(regaddr);
if( IIC_Wait_Ack() == 1 ) printf("error -2\r\n");
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;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
在文件 bsp_sht20.h 中,编写如下代码。
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:https://oshwhub.com/forum
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*
Change Logs:
* Date Author Notes
* 2024-03-19 LCKFB-LP first version
*/
#ifndef __BSP_SHT20_H__
#define __BSP_SHT20_H__
#include "stm32f4xx.h"
//端口移植
#define RCC_SHT20 RCC_AHB1Periph_GPIOA
#define PORT_SHT20 GPIOA
#define GPIO_SDA GPIO_Pin_2
#define GPIO_SCL GPIO_Pin_1
//设置SDA输出模式
#define SDA_OUT() { \
GPIO_InitTypeDef GPIO_InitStructure; \
GPIO_InitStructure.GPIO_Pin = GPIO_SDA; \
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; \
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; \
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; \
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; \
GPIO_Init(PORT_SHT20, &GPIO_InitStructure); \
}
//设置SDA输入模式
#define SDA_IN() { \
GPIO_InitTypeDef GPIO_InitStructure; \
GPIO_InitStructure.GPIO_Pin = GPIO_SDA; \
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; \
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; \
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; \
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; \
GPIO_Init(PORT_SHT20, &GPIO_InitStructure); \
}
//获取SDA引脚的电平变化
#define SDA_GET() GPIO_ReadInputDataBit(PORT_SHT20, GPIO_SDA)
//SDA与SCL输出
#define SDA(x) GPIO_WriteBit(PORT_SHT20, GPIO_SDA, (x?Bit_SET:Bit_RESET) )
#define SCL(x) GPIO_WriteBit(PORT_SHT20, GPIO_SCL, (x?Bit_SET:Bit_RESET) )
void SHT20_GPIO_INIT(void);
float SHT20_Read(unsigned char regaddr);
#endif
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
移植验证
在自己工程中的 main 主函数中,编写如下。
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:https://oshwhub.com/forum
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*
Change Logs:
* Date Author Notes
* 2024-03-19 LCKFB-LP first version
*/
#include "board.h"
#include "bsp_uart.h"
#include <stdio.h>
#include "bsp_sht20.h"
#define T_ADDR 0xf3 // 温度
#define PH_ADDR 0xf5 // 湿度
int main(void)
{
board_init();
uart1_init(115200U);
SHT20_GPIO_INIT();
delay_ms(1000);
printf("SHT20 Start!!\r\n");
while(1)
{
printf("温度 = %.2f ℃\r\n", SHT20_Read(T_ADDR) );
printf("湿度 = %.2f %%RH\r\n",SHT20_Read(PH_ADDR) );
printf("\n");
delay_ms(1000);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
上电现象:
代码下载
链接在开发板介绍
章节的离线资料下载!!