能够感应外界温湿度的器件。

DHT11数字温湿度传感器是自带校准标准数字信号输出温湿度 复合传感器。

传感器性能说明:

测量范围:20%~90%RH 0~50℃

湿度精度:+-5%RH

温度精度:+-2℃

分辨率:1(可感知的被测量的最小变化能力)

数据格式

接收到传感器的40位数据:

0011 0101 0000 0000 0001 1000 0000 0000 0100 1101

湿度高8位        湿度低8位    温度高8位     温度低8位    校验位

传感器电源引脚说明

供电3.3-5v(宽电压)。传感器上电之后 需等待1s越过不稳定状态(可以忽略不计)

DHT100(4阵单排直插)

1、VCC (供电引脚)

2、DATA    (串行数据,单总线)

3、NC  (空脚,需要悬空。无效,可能为了起到更好的固定效果而存在

4、GND    (表示接地,电源负极)

计算

前32位相加=校验位

0011 0101 + 0000 0000 + 0001 1000 + 0000 0000 = 0100 1101(表示数据接收正确)

湿度高8位:0011 0101 = 35H = 53%RH

温度高8位:0001 1000 = 18H = 24℃

总结:低8位是0,所以可以互虐不看。

MCU角度分析:

用户MCU发送开始信号后,DHT11从低功耗模式转换为高速模式,等待主机开始信号结束后,给MCU发送响应信号,接着DHT11发送40bit数据,触发一次采集。(用户可选择读取部分数据 , MCU唤醒DHT11

DHT11角度分析:

在从模式下DHT11接收到开始信号并触发一次温湿度采集,如果第二次为接收到MCU开始信号,DHT11不会主动温湿度采集。采集数据结束后转换到低功耗模式,(相当于休眠模式等待MCU唤醒

数据时序(编码依据)

数据时序图:

MCU发开始信号及DHT11响应时序图:

编码思路:

一、单片机上电1s内不读取(不重要)

二、主机(单片机)发送开始信号:
1、总线空闲状态是高电平(先拉高)
2、主机拉低电平持续时间>18ms
3、主机拉高电平(单机片引脚设置为输入)

三、从机(DHT100传感器)收到信号响应应答:
    从机拉低电平,主机读取电平被拉低持续80us后从机拉高电平再次持续80us,
    直到高电平结束。意味着主机可以接收数据。

四:主机开始接收数据
1、主机IO设置为输入
2、从机把总线电平拉低,主机读取总线电平,直到低电平结束(大约50us),
   (从机发回来的数据位表示)
    从机拉高电平,延时40us左右(取 26-70us之间 中间值),主机再次读取电平。
    (在40us内读到的高电平表示0,超出40us表示1)
3、重复执行1、2两步40次。(目的读取40位)

五:从机拉低总线50us,随后总线由上拉电阻拉高电平进入空闲状态。

具体实现

/*
 * dht11.c
 *
 * created: 2022/06/22
 *  author:
 */

#include "ls1b.h"
#include "ls1b_gpio.h"
#include "dht11.h"
#include "tick.h"

//单总线 控数据引脚 电平高低     gpio输入的值(传感器给的电平高低)
void DHT11_DQ_OUT(int e)
{
    gpio_enable(DHT11_IO, e);    // Pin: SPI0_CS2
}

void DHT11_DQ_IN(void)
{
    gpio_read(DHT11_IO);
}

//单总线设置为输入
void DHT11_IO_IN(void)
{
    gpio_enable(DHT11_IO, DIR_IN);
}

//单总线设置为输出
void DHT11_IO_OUT(void)
{
    gpio_enable(DHT11_IO, DIR_OUT);
}

//复位(开始信号)DHT11
void DHT11_Reset(void)
{
    DHT11_IO_OUT(); //设置 为 输出
    DHT11_DQ_OUT(0); //io为低电平。
    delay_ms(19);   //持续时间 >=18ms
    DHT11_DQ_OUT(1);    //主机拉高
    delay_us(30); //持续时间30us
}

//检测传感器(判断是否响应)
unsigned char DHT11_Check(void)
{
    unsigned char flag=0; //延时条件
    DHT11_IO_IN();  //改变IO输入方向为输入   电平接的复位信号的高电平。
    while(gpio_read(DHT11_IO)&&flag<100)    //
    {
        flag++;
        delay_us(1);
    }
    if(flag>=100)return 1;
    else flag=0;

    while(!gpio_read(DHT11_IO)&&flag<100)
    {
        flag++;
        delay_us(1);
    }
    if(flag>=100)
        return 1;
    return 0;
}

//读取一位
unsigned char DHT11_Read_Bit()
{
    unsigned char flag;
    while(gpio_read(DHT11_IO)&&flag<100)
    {
        flag++;
        delay_us(1);
        if(flag==99)
        {
            return -1;
        }
    }
    flag=0;
    while(gpio_read(DHT11_IO)&&flag<100)
    {
        flag++;
        delay_us(1);
    }
    delay_us(40); //取中间值。。26-70us
    if(gpio_read(DHT11_IO))return 1;
    else return 0;
}

//读一字
unsigned char DHT11_Read_Byte()
{
    unsigned char i,flag;
    flag=0;
    for(i=0; i<8; i++)
    {
        flag<<=1;
        flag|=DHT11_Read_Bit();
    }
    return flag;
}

//读取温湿度数据
unsigned char DHT11_read_Data(unsigned int *temp,unsigned int *huami)
{
    unsigned char buf[5];   //五个字节
    unsigned char i;
    DHT11_Reset();      //复位。
    if(DHT11_Check()==0)
    {
        for(i=0; i<5; i++)
        {
            buf[i]=DHT11_Read_Byte();
        }
        if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
        {
            *temp = buf[0]*10+buf[1];
            *huami= buf[2]*10+buf[3];
        }
    }
    else return 1;
    return 0;
}

//初始化
unsigned char DHT11_Init(void)
{
    gpio_enable(DHT11_IO,DIR_OUT);
    gpio_write(DHT11_IO,1);
    DHT11_Reset();
    return DHT11_Check();
}
最后修改:2022 年 06 月 26 日 12 : 59 PM