基于51单片机的DHT11传感器

关于DHT11传感器

DHT11传感器是有已校准数字信号输出的温湿度传感器的,之所以使用DHT11来做温湿度传感器的原因有以下三点:

  1. DHT11的时序简单。
  2. DHT11是国产的,全中文的参考手册,不用担心英文看不懂。
  3. 功能少,只有一个测量温湿度的功能。

参数特性

基于51单片机的DHT11传感器_第1张图片
注:DHT11温湿度传感器的测量范围,以及精度、分辨率。如果超出了这个范围,那么DHT11就不能够使用了。
引脚说明
基于51单片机的DHT11传感器_第2张图片
注意供电范围是 **3 -5.5 V。**如果超出这个范围,传感器可能会烧、假如低于这个范围,可能传感器会读出错误的温湿度数据或者压根就罢工了。

基于51单片机的DHT11传感器_第3张图片
这个是数据手册上显示的DHT11典型的电路连接方法,我们再数据口上要接上一个上拉电阻。供电所使用的为7805的稳压电源,也就是5V。实际上,只要我们满足他的供电电压范围,都是能够工作的。

数据格式

基于51单片机的DHT11传感器_第4张图片
DHT11用的是单总线协议,一次传送40位的数据。 注意了,看到这一句话,也就是说我们每次读取DHT11的数据时,都要一次性读取40次,也就是读取40位。并且数据前16位是与湿度相关的,中间16位是与温度相关的,最后八位是用来校验的,当我们校验成功后,证明这一次的温湿度结果正确的,我们单片机就可以使用这个温湿度值;如果校验不通过,那么就代表我们这次读取出来的温湿度值,是错误的(也许是我们的时序错误了,也许是传感器的问题),我们不进行采样。
基于51单片机的DHT11传感器_第5张图片
基于51单片机的DHT11传感器_第6张图片
DHT11的总体通信流程。第一步:主机先发送开始信号,从机会返回一个相应信号进行应答。 第二步:主机信号线拉高准备接收数据。 第三部:开始接收数据(一次接收40位)。

步骤

步骤一:DHT11 上电后(DHT11 上电后要等待 1S 以越过不稳定状态在此期间不能发送任何指令),测试环境
温湿度数据,幵记录数据,同时 DHT11 的 DATA 数据线由上拉电阻拉高一直保持高电平;此时 DHT11 的
DATA 引脚处于输入状态,时刻检测外部信号。

步骤二:微处理器的 I/O 设置为输出同时输出低电平,且低电平保持时间不能小于 18ms,然后微处理器的 I/O
设置为输入状态,由于上拉电阻,微处理器的 I/O 即 DHT11 的 DATA 数据线也随之变高,等待 DHT11 作
出回答信号,发送信号如图所示:
基于51单片机的DHT11传感器_第7张图片
步骤三:DHT11 的 DATA 引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后 DHT11 的 DATA
引脚处于输出状态,输出 80 微秒的低电平作为应答信号,紧接着输出 80 微秒的高电平通知外设准备接
收数据,微处理器的 I/O 此时处于输入状态,检测到 I/O 有低电平(DHT11 回应信号)后,等待 80 微秒
的高电平后的数据接收,发送信号如图所示:

基于51单片机的DHT11传感器_第8张图片

步骤四:由 DHT11 的 DATA 引脚输出 40 位数据,微处理器根据 I/O 电平的变化接收 40 位数据,位数据“0”
的格式为: 50 微秒的低电平和 26-28 微秒的高电平,位数据“1”的格式为: 50 微秒的低电平加 70
微秒的高电平。位数据“0”、“1”格式信号如图所示:
基于51单片机的DHT11传感器_第9张图片
(我们可以把这一段的时序理解为,我们主机先把数据线拉低50us,然后延时等待40us,然后再去读取信号线的电平,如果为低电平,则为位“0”;如果为高电平,则为位“1”)。

结束信号:DHT11 的 DATA 引脚输出 40 位数据后,继续输出低电平 50 微秒后转为输入状态,由于上拉电阻随
之变为高电平。但 DHT11 内部重测环境温湿度数据,幵记录数据,等待外部信号的到来。

方法总结:

一. 单片机上点后1s内不读取(不重要)

二. 主机(单片机)发送起始信号:
1.主机先拉高data。
2.拉低data延迟18ms。
3.拉高data(单片机引脚设置为输入)。

三. 从机(DHT11)收到起始信号后进行应答:
从机拉低data,主机读取到data线被拉低持续80us后从机拉高data线,
持续80us,直到高电平结束,意味着主机可以开始接受数据。

四. 主机开始接收数据:
1.主机先把data线拉高(io设置为输入)。
2.从机把data线拉低,主机读取data线电平,直到低电平结束(大约50us)
从机拉高data线后,延迟40us左右(28~70us之间)主机再次读取data线
电平,如果为低电平,则为“0”,如果为高电平,则为“1”。
3.继续重复上述1,2步骤累计40次。

五. data线拉低50us代表读取结束

六. 校验数据

代码

(代码来源于网络,暂未核验是否可用)

//****************************************************************//
// DHT11使用范例
//单片机 : AT89S52 或 STC89C52RC
// 功能 :串口发送温湿度数据 波特率 9600
//硬件连接: P2.0口为通讯口连接DHT11,DHT11的电源和地连接单片机的电源和地,单片机串口加MAX232连接电脑
#include 
#include 
//
typedef unsigned char U8; /* defined for unsigned 8-bits integer variable 无符号8位整型变量 */
typedef signed char S8; /* defined for signed 8-bits integer variable 有符号8位整型变量 */
typedef unsigned int U16; /* defined for unsigned 16-bits integer variable 无符号16位整型变量 */
typedef signed int S16; /* defined for signed 16-bits integer variable 有符号16位整型变量 */
typedef unsigned long U32; /* defined for unsigned 32-bits integer variable 无符号32位整型变量 */
typedef signed long S32; /* defined for signed 32-bits integer variable 有符号32位整型变量 */
typedef float F32; /* single precision floating point variable (32bits) 单精度浮点数(32位长度) */
typedef double F64; /* double precision floating point variable (64bits) 双精度浮点数(64位长度) */
//
#define uchar unsigned char
#define uint unsigned int
#define Data_0_time 4
//--------------- --------------------//
//----------------IO口定义区--------------------//
//-------------- --------------------------//
sbit P2_0 = P2^0 ;//DATA
sbit P2_1 = P2^1 ;
sbit P2_2 = P2^2 ;
sbit P2_3 = P2^3 ;
//--------- ------------------------------------//
//----------------定义区--------------------//
//--------------------- -----------------------//
U8 U8FLAG,k;
U8 U8count,U8temp;
U8 U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;
U8 U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;
U8 U8comdata;
U8 outdata[5]; //定义发送的字节数
U8 indata[5];
U8 count, count_r=0;
U8 str[5]={"RS232"};
U16 U16temp1,U16temp2;
 
SendData(U8 *a)
{
    outdata[0] = a[0];
    outdata[1] = a[1];
    outdata[2] = a[2];
    outdata[3] = a[3];
    outdata[4] = a[4];
    count = 1;
    SBUF=outdata[0];
}
 
void Delay(U16 j)
{
    U8 i;
    for(;j>0;j--)
    {
        for(i=0;i<27;i++);
    }
}
 
void Delay_10us(void)
{
    U8 i;
    i--;
    i--;
    i--;
    i--;
    i--;
    i--;
}
 
void COM(void)
{
    U8 i;
    for(i=0;i<8;i++)
    {
    U8FLAG=2;
    //----------------------
    P2_1=0 ; //T
    P2_1=1 ; //T
    //----------------------
    while((!P2_0)&&U8FLAG++);
    Delay_10us();
    Delay_10us();
    // Delay_10us();
    U8temp=0;
    if(P2_0)U8temp=1;
    U8FLAG=2;
    while((P2_0)&&U8FLAG++);
    //----------------------
    P2_1=0 ; //T
    P2_1=1 ; //T
    //----------------------
    //超时则跳出for循环
    if(U8FLAG==1)break;
    //判断数据位是0还是1
    // 如果高电平高过预定0高电平值则数据位为 1
    U8comdata<<=1;
    U8comdata|=U8temp; //0
    }//rof
}
 
//------------  --------------------
//-----湿度读取子程序 ------------
//----------------------  ----------
//----以下变量均为全局变量--------
//----温度高8位== U8T_data_H------
//----温度低8位== U8T_data_L------
//----湿度高8位== U8RH_data_H-----
//----湿度低8位== U8RH_data_L-----
//----校验 8位 == U8checkdata-----
//----调用相关子程序如下----------
//---- Delay();, Delay_10us();COM();
//---------------------    -----------
void RH(void)
{
    //主机拉低18ms
    P2_0=0;
    Delay(180);
    P2_0=1;
    //总线由上拉电阻拉高 主机延时20us
    Delay_10us();
    Delay_10us();
    Delay_10us();
    Delay_10us();
    //主机设为输入 判断从机响应信号
    P2_0=1;
    //判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行
    if(!P2_0) //T !
    {
        U8FLAG=2;
        //判断从机是否发出 80us 的低电平响应信号是否结束
        while((!P2_0)&&U8FLAG++);
        U8FLAG=2;
        //判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
        while((P2_0)&&U8FLAG++);
        //数据接收状态
        COM();
        U8RH_data_H_temp=U8comdata;
        COM();
        U8RH_data_L_temp=U8comdata;
        COM();
        U8T_data_H_temp=U8comdata;
        COM();
        U8T_data_L_temp=U8comdata;
        COM();
        U8checkdata_temp=U8comdata;
        P2_0=1;
        //数据校验
        U8temp=(U8T_data_H_temp+U8T_data_L_temp+U8RH_data_H_temp+U8RH_data_L_temp);
        if(U8temp==U8checkdata_temp)
        {
            U8RH_data_H=U8RH_data_H_temp;
            U8RH_data_L=U8RH_data_L_temp;
            U8T_data_H=U8T_data_H_temp;
            U8T_data_L=U8T_data_L_temp;
            U8checkdata=U8checkdata_temp;
        }//fi
    }//fi
}
 
//---------------------------------------
//main()功能描述: AT89C51 11.0592MHz 串口发
//送温湿度数据,波特率 9600
//----------------------------------------------
void main()
{
    U8 i,j;
    //uchar str[6]={"RS232"};
    /* 系统初始化 */
    TMOD = 0x20; //定时器T1使用工作方式2
    TH1 = 253; // 设置初值
    TL1 = 253;
    TR1 = 1; // 开始计时
    SCON = 0x50; //工作方式1,波特率9600bps,允许接收
    ES = 1;
    EA = 1; // 打开所以中断
    TI = 0;
    RI = 0;
    SendData(str) ; //发送到串口
    Delay(1); //延时100US(12M晶振)
    while(1)
    {
        //------------------------
        //调用温湿度读取子程序
        RH();
        //串口显示程序
        //--------------------------
        str[0]=U8RH_data_H;
        str[1]=U8RH_data_L;
        str[2]=U8T_data_H;
        str[3]=U8T_data_L;
        str[4]=U8checkdata;
        SendData(str) ; //发送到串口
        //读取模块数据周期不易小于 2S
        Delay(20000);
    }//elihw
}// main
 
void RSINTR() interrupt 4 using 2
{
    U8 InPut3;
    if(TI==1) //发送中断
    {
        TI=0;
        if(count!=5) //发送完5位数据
        {
            SBUF= outdata[count];
            count++;
        }
    }
    if(RI==1) //接收中断
    {
        InPut3=SBUF;
        indata[count_r]=InPut3;
        count_r++;
        RI=0;
        if (count_r==5)//接收完4位数据
        {
            //数据接收完毕处理。
            count_r=0;
            str[0]=indata[0];
            str[1]=indata[1];
            str[2]=indata[2];
            str[3]=indata[3];
            str[4]=indata[4];
            P0=0;
        }
    }

参考出处

DHT11温湿度传感器手册:https://wenku.baidu.com/view/d1aec72158fb770bf78a55e0.html

你可能感兴趣的