这篇文章距离最后更新已过251 天,如果文章内容或图片资源失效,请留言反馈,我会及时处理,谢谢!
产品概述
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度 复合传感器。应用专用的数字模块采集技术和温湿度传感技术,可以将获取到的环境温湿度信号通过单总线传输;信号中携带有校验码,一定程度上保证了数据的准确性。
性能指标
参数 | 最小 | 最大 |
---|
温度范围 | -20℃ | 60℃ |
湿度范围 | 5%RH | 95%RH |
电压 | 3.3V | 5.5V |
电流 | 0.06mA | 1.0mA |
引脚说明:
- VDD 供电3.3~5.5V DC
- DATA 串行数据,单总线
- NC 空脚
- GND 接地,电源负极
工作原理
数据时序图
- 起始信号:微处理器把数据总线(SDA)拉低一段时间至少 18ms(最大不得超过 30ms),在拉高20us-40us,通知传感器准备数据。
- 响应信号:传感器把数据总线(SDA)拉低 83µs,再拉高 87µs 以响应主机的起始信号。
数据格式:收到主机起始信号后,传感器一次性从数据总线(SDA)串出 40 位数据,高位先出
当检测到这一位数据的高电平后,我们要看这段高电平究竟会持续多长时间,0信号的高电平持续26-28us,1信号则持续70us。所以在上一步检测到高电平之后我们不妨等一等,等个30us看看高电平是不是还是存在,若还是高电平,那这一位信号就是1信号,若已经变低了,就是0信号,将这个1或0赋值给一个变量。
- 温度:温度高位为温度整数部分数据,温度低位为温度小数部分数据,且温度低位 Bit8 为 1 则表示负温度,否则 为正温度
- 湿度:湿度高位为湿度整数部分数据,湿度低位为湿度小数部分数
- 校验位:校验位=湿度高位+湿度低位+温度高位+温度低位
以上内容来自奥松电子DHT11官方文档,详细内容请查看文档
代码实例
树莓派Python3代码实例
1 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
|
#!/usr/bin/python3 coding=utf-8
import RPi.GPIO as GPIO
import time
data = 18 # DHT11的data引脚连接到的树莓派的GPIO引脚,使用BCM编号
tmp=[] # 用来存放读取到的数据
a,b=0,0
def delayMicrosecond(t): # 微秒级延时函数
start,end=0,0 # 声明变量
start=time.time() # 记录开始时间
t=(t-3)/1000000 # 将输入t的单位转换为秒,-3是时间补偿
while end-start<t: # 循环至时间差值大于或等于设定值时
end=time.time() # 记录结束时间
def DHT11():
GPIO.setmode(GPIO.BCM) # 设置为BCM编号模式
GPIO.setwarnings(False)
del tmp[0:] # 删除列表
time.sleep(1) # 延时1秒
GPIO.setup(data, GPIO.OUT) # 设置GPIO口为输出模式
#GPIO.output(data,GPIO.HIGH) # 设置GPIO输出高电平
#delayMicrosecond(10*1000) # 延时10毫秒
GPIO.output(data,GPIO.LOW) # 设置GPIO输出低电平
delayMicrosecond(25*1000) # 延时25毫秒
GPIO.output(data,GPIO.HIGH) # 设置GPIO输出高电平
GPIO.setup(data, GPIO.IN) # 设置GPIO口为输入模式
a=time.time() # 记录循环开始时间
while GPIO.input(data): # 一直循环至输入为低电平
b=time.time() # 记录结束时间
if (b-a)>0.1: # 判断循环时间是否超过0.1秒,避免程序进入死循环卡死
break # 跳出循环
a=time.time()
while GPIO.input(data)==0: # 一直循环至输入为高电平
b=time.time()
if (b-a)>0.1:
break
a=time.time()
while GPIO.input(data): # 一直循环至输入为低电平
b=time.time()
if (b-a)>=0.1:
break
for i in range(40): # 循环40次,接收温湿度数据
a=time.time()
while GPIO.input(data)==0: #一直循环至输入为高电平
b=time.time()
if (b-a)>0.1:
break
delayMicrosecond(28) # 延时28微秒
if GPIO.input(data): # 超过28微秒后判断是否还处于高电平
tmp.append(1) # 记录接收到的bit为1
a=time.time()
while GPIO.input(data): # 一直循环至输入为低电平
b=time.time()
if (b-a)>0.1:
break
else:
tmp.append(0) # 记录接收到的bit为0
humidity_bit=tmp[0:8] # 分隔列表,第0到7位是湿度整数数据
humidity_point_bit=tmp[8:16]# 湿度小数
temperature_bit=tmp[16:24] # 温度整数
temperature_point_bit=tmp[24:32] # 温度小数
check_bit=tmp[32:40] # 校验数据
humidity_int=0
humidity_point=0
temperature_int=0
temperature_point=0
check=0
for i in range(8): # 二进制转换为十进制
humidity_int+=humidity_bit[i]*2**(7-i)
humidity_point+=humidity_point_bit[i]*2**(7-i)
temperature_int+=temperature_bit[i]*2**(7-i)
temperature_point+=temperature_point_bit[i]*2**(7-i)
check+=check_bit[i]*2**(7-i)
humidity=humidity_int+humidity_point/10
temperature=temperature_int+temperature_point/10
check_tmp=humidity_int+humidity_point+temperature_int+temperature_point
if check==check_tmp and temperature!=0 and temperature!=0: # 判断数据是否正常
print("Temperature is ", temperature,"℃\nHumidity is ",humidity,"%")# 打印温湿度数据
else:
print("error")
while True:
DHT11()
GPIO.cleanup()
time.sleep(5)
|
树莓派C语言代码实例
1 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
|
//
//mydht11.c
//gcc dht11.c -o dht11 -lwiringPi
//代码非原创,已经找不到原作者了,感谢大佬
//
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef unsigned long uint32;
#define HIGH_TIME 32
int pinNumber = 1; //use gpio1 to read data
uint32 databuf;
uint8 readSensorData(void)
{
uint8 crc;
uint8 i;
pinMode(pinNumber,OUTPUT); // set mode to output
digitalWrite(pinNumber, 1); // output a low level
delayMicroseconds(4);
digitalWrite(pinNumber, 0); // output a high level
delay(25);
digitalWrite(pinNumber, 1); // output a low level
delayMicroseconds(60);
pinMode(pinNumber, INPUT); // set mode to input
pullUpDnControl(pinNumber,PUD_UP);
if(digitalRead(pinNumber)==0) //SENSOR ANS
{
while(!digitalRead(pinNumber)); //wait to high
delayMicroseconds(80);
for(i=0;i<32;i++)
{
while(digitalRead(pinNumber)); //data clock start
while(!digitalRead(pinNumber)); //data start
delayMicroseconds(HIGH_TIME);
databuf*=2;
if(digitalRead(pinNumber)==1) //1
{
databuf++;
}
}
for(i=0;i<8;i++)
{
while(digitalRead(pinNumber)); //data clock start
while(!digitalRead(pinNumber)); //data start
delayMicroseconds(HIGH_TIME);
crc*=2;
if(digitalRead(pinNumber)==1) //1
{
crc++;
}
}
return 1;
}
else
{
return 0;
}
}
int main (void)
{
if (-1 == wiringPiSetup()) {
//printf("Setup wiringPi failed!");
return 1;
}
pinMode(pinNumber, OUTPUT); // set mode to output
digitalWrite(pinNumber, 1); // output a high level
//while(1)
//{
pinMode(pinNumber,OUTPUT); // set mode to output
digitalWrite(pinNumber, 1); // output a high level
//delay(3000);
if(readSensorData())
{
printf("OK!\n");
printf("RH:%d.%d\n",(databuf>>24)&0xff,(databuf>>16)&0xff);
printf("TMP:%d.%d\n",(databuf>>8)&0xff,databuf&0xff);
databuf=0;
}
else
{
printf("Error!\n");
databuf=0;
}
//}
return 0;
}
|
ESP32C语言代码实例(ESP-IDF官方编译烧写工具)
1 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
|
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#define DHT11_PIN (15) //可通过宏定义,修改引脚
#define DHT11_CLR gpio_set_level(DHT11_PIN, 0) //设为低电平
#define DHT11_SET gpio_set_level(DHT11_PIN, 1) //设为高电平
#define DHT11_IN gpio_set_direction(DHT11_PIN, GPIO_MODE_INPUT) //设为输入模式
#define DHT11_OUT gpio_set_direction(DHT11_PIN, GPIO_MODE_OUTPUT) //设为输出模式
uint8_t DHT11Data[4] = {0};
uint8_t Temp, Humi;
// us延时函数,误差不能太大
void DelayUs(uint32_t nCount)
{
ets_delay_us(nCount);
}
//DHT11初始化
void DHT11_Start(void)
{
/***************************
*
* 主机发送给DHT11复位信号
*
* 首先主机拉低总线至少 18ms,然后再拉高总线,延时 20~40us,取中间值 30us,此时复位信号发送完毕。
*
* **********************************/
DHT11_OUT; //设置端口方向
DHT11_CLR; //拉低端口
DelayUs(19 * 1000);
// vTaskDelay(19 * portTICK_RATE_MS); //持续最低18ms;
DHT11_SET; //主机拉高端口
DelayUs(30); //总线由上拉电阻拉高,主机延时30uS;
/********************************
* DHT11发送响应信号
*
* DHT11 检测到复位信号后,触发一次采样,
* 并拉低总线 80us 表示响应信号,告诉主机数据已经准备好了;
* 然后 DHT11 拉高总线 80us,
* 之后开始传输数据。如果检测到响应信号为高电平,
* 则 DHT11 初始化失败,
* 请检查线路是否连接正常。
*
*******************************/
DHT11_IN; //设置端口方向
while (!gpio_get_level(DHT11_PIN))
; // DHT11等待80us低电平响应信号结束
while (gpio_get_level(DHT11_PIN))
; // DHT11 将总线拉高80us
}
uint8_t DHT11_ReadValue(void)
{
uint8_t i, sbuf = 0;
for (i = 8; i > 0; i--)
{
sbuf <<= 1;
while (!gpio_get_level(DHT11_PIN))
;
DelayUs(40); // 延时 30us 后检测数据线是否还是高电平
if (gpio_get_level(DHT11_PIN))
{
sbuf |= 1;
}
else
{
sbuf |= 0;
}
while (gpio_get_level(DHT11_PIN))
;
}
return sbuf;
}
uint8_t DHT11_ReadTemHum(uint8_t *buf)
{
uint8_t check;
buf[0] = DHT11_ReadValue();
buf[1] = DHT11_ReadValue();
buf[2] = DHT11_ReadValue();
buf[3] = DHT11_ReadValue();
check = DHT11_ReadValue();
if (check == buf[0] + buf[1] + buf[2] + buf[3])
return 1;
else
return 0;
}
void app_main(void)
{
// printf("ESP32 DHT11 TEST:%s,%s!\r\n", __DATE__, __TIME__);
gpio_pad_select_gpio(DHT11_PIN);
while (1)
{
DHT11_Start();
if (DHT11_ReadTemHum(DHT11Data))
{
Temp = DHT11Data[2];
Humi = DHT11Data[0];
printf("ESP32 DHT11 TEST:%s,%s!\r\n", __DATE__, __TIME__);
printf("Temp=%d.%d, Humi=%d.%d\r\n", Temp,DHT11Data[3],Humi,DHT11Data[1]);
}
else
{
printf("DHT11 Error!\r\n");
}
vTaskDelay(5000 / portTICK_PERIOD_MS);
}
}
|
附录:
树莓派GPIO
暂无评论