• DHT11温湿度传感器


    一.硬件介绍

    RH是相对湿度,是用零点温度来定义的,一般,RH在45%~65%之间最为合适。

    注:NTC为热敏电阻,输出为:单总线数字信号,单线双向串行通讯。

    注:上拉电阻情况下,配置为开漏输出,可以增加驱动能力,减小CPU功耗。

    二.程序关键点:1)引脚输入与输出的准确切换,2)输出电平的准确延迟,3)输入电平的等待与延迟读取以及等待的时间限制。

    1.MCU如何设置开始信号?

    /*
    由MCU向DHT11发送一次开始信号,总线空闲状态为高电平,MCU把总线拉低至少18ms,
    保证DHT11能检测到开始信号,主机发送开始信号后,可以切换到输入模式,或者切换到
    高电平均可,切换到高电平时间通常为20~40us,然后开始读取响应信号.
    */
    void DHT11_Rst(void)   
    {                 
    DHT11_IO_OUT();  //配置引脚为通用推挽输出模式
    DAOBB = 0;  //拉低DQ
        SysTickDelay(20000);//至少18ms
    DAOBB = 1; 
    SysTickDelay(30);//主机拉高20~40us
    }

    2.MCU如何接受响应信号?

    /*
    等待DHT11的回应
    返回1:未检测到DHT11的存在
    返回0:存在DHT11接受到主机的开始信号后,等待主机的开始信号结束,
    然后发送80us的低电平响应信号,发送响应信号后,在把总线拉高80us,准备发送数据*/
    u8 DHT11_Check(void)   
    {   
    u8 retry=0;
    DHT11_IO_IN();//将A11口设为输入
      /*&&与<的优先级是<高于&&*/
        while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us
    {
    retry++;
    SysTickDelay(1);//这里系统滴答函数要配置为1US的中断

    if(retry>=100)return 1;
    else retry=0;
        while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us
    {
    retry++;
    SysTickDelay(1);
    }
    if(retry>=100)return 1;   
    return 0;
    }

    3.如何读取一个位的高低电平?前提是已经有响应信号,这样去读取数据才有意思。
    一个位的高低电平是根据总线上的高电平的时间长度来判断的,说白了,就是低电平一旦结束,再过28us,总线上的电平为高,这个位的电平就是高电平,总线上的电平为低,这个位的电平就是低电平。所以我们只要等待总线上的低电平结束,过了28us以后再70us之前去读总线上的电平,就能知道具体的一位的电平是多少了。但我们不能无限制的等待低电平结束,假如器件故障或其他原因,总线上始终低电平,这样程序就会在等待中死去,所以我们必须加一个等待时间的限制,超过等待时间,我们就放弃这次等待。为了使读取后总线上的高低电平不影响下一次的读取数据,我们还加了一个高电平的限时等待。

    /*从DHT11读取一个位,返回值:1/0。
    每一bit数据都以50us的低电平时序开始,高电平的宽度决定了bit数据位的0或1,
    高电平状态在26~28us时,表示数据位为0,高电平状态在70us时,表示数据位为1.
    DHT11_DQ_IN是读取对应端口引脚的输入电平,在读之前,该引脚要配置为上拉下拉输入模式
    */
    u8 DHT11_Read_Bit(void)  
    {
      u8 retry=0;
    while(DHT11_DQ_IN&&retry<100)//读取高电平中,等待变为低电平,/*&&与<的优先级是<高于&&*/
    {
    retry++;
    SysTickDelay(1);
    }
    retry=0;
    while(!DHT11_DQ_IN&&retry<100)//读取低电平中,等待变高电平
    {
    retry++;
    SysTickDelay(1);
    }
    SysTickDelay(40);//等待40us
    if(DHT11_DQ_IN)return 1;
    else return 0;  
    }

    //从DHT11读取一个字节
    //返回值:读到的数据
    u8 DHT11_Read_Byte(void)    
    {        
        u8 i,dat;
        dat=0;
    for (i=0;i<8;i++) 
    {
        dat<<=1; 
       dat|=DHT11_Read_Bit();
        }    
        return dat;
    }

    //从DHT11读取一次数据
    //temp:温度值(范围:0~50°)
    //humi:湿度值(范围:20%~90%)
    //返回值:0,正常;1,读取失败
    u8 DHT11_Read_Data(u8 *temp,u8 *humi)    
    {        
      u8 buf[5];
    u8 i;
    DHT11_Rst();
    if(DHT11_Check()==0)
    {
    for(i=0;i<5;i++)//读取40位数据
    {
    buf[i]=DHT11_Read_Byte();
    }
    if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
    {
    *humi=buf[0];
    *temp=buf[2];
    }
    }else return 1;
    return 0;     
    }

  • 相关阅读:
    网络时钟同步SOCKET代码
    NTP时间同步之同步时钟要领
    3分钟 Markdown 快速入门(超详细)(Day_33)
    如何在idea中将项目生成API文档(超详细)(Day_32)
    多条件分页 (Day_31)
    常见判断错误 (Day_30)
    HTML 标签隐藏占用空间与不占用空间(Day_29)
    EasyUI_使用datagrid分页 (Day_28)
    (xxx) is not defined at HTMLInputElement.onblur(Day_27)
    EasyUI系列—点击按钮加载tabs_day26
  • 原文地址:https://www.cnblogs.com/Ph-one/p/4333384.html
Copyright © 2020-2023  润新知