打印

求助 DHT11测量湿度不正常

[复制链接]
8198|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
milktang|  楼主 | 2010-10-25 17:36 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
各位老师,我对温度湿度进行测量,使用数字温湿度传感器DHT11,显示测量值时发现一上电湿度数值就不停跳动,跳动数值幅度有十几,温度数值基本没变,感觉测量湿度数值不正确,请各位帮忙指导下,谢谢。
程序如下,MCU为16F873,晶振为10MHz
#include "pic.h"
#define uchar unsigned char
#define uint unsigned int
#define LCD_RS RC5
#define LCD_RW RC6
#define LCD_EN RC7
#define DH RC4 //定义DHT11数据端口
#define DH_HIGH() TRISC4=1 //设置数据口为输入
#define DH_LOW() TRISC4=0;DH = 0 //设置数据口为输出
uchar RH_data_H_temp,RH_data_L_temp,T_data_H_temp,T_data_L_temp,checkdata_temp;
uchar RH_data_H,RH_data_L,T_data_H,T_data_L,checkdata;
uchar flag,temp,comdata;

void delayus(uint x,uchar y)
{ uint i; uchar j;
   for(i=x;i>0;i--);
    for(j=y;j>0;j--);
}

void COM()
{ uchar i;
   for(i=0;i<8;i++)
    { flag=2;
       while((!(DH))&&flag++);//等待高电平
          if(flag==1)break;
           delayus(0,2);
           delayus(0,2);
           delayus(0,2);
           //delayus(0,2);
           temp=0;
           if(DH)temp=1;
             flag=2;
           while((DH)&&flag++); //等待低电平
            //超时则跳出for循环
           if(flag==1)break;
           //判断数据位是0还是1 // 如果高电平高过预定0高电平值则数据位为 1
             comdata<<=1;
             comdata|=temp; //0
         }
}
//--------------------------------
//-----湿度读取子程序 ------------
//--------------------------------
//----以下变量均为全局变量--------
//----温度高8位== U8T_data_H------
//----温度低8位== U8T_data_L------
//----湿度高8位== U8RH_data_H-----
//----湿度低8位== U8RH_data_L-----
//----校验 8位 == U8checkdata-----
//--------------------------------
void RH(void)
{    //主机拉低18ms
       DH_LOW();
       delayus(5000,200);
       DH_HIGH(); //总线由上拉电阻拉高 主机延时20-40us
       delayus(0,2);
       delayus(0,2);
       delayus(0,2);
       delayus(0,2);
        //主机设为输入 判断从机响应信号
       DH_HIGH();
        //判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行
         if(!DH)
        {     flag=2;  
              //判断从机是否发出 80us 的低电平响应信号是否结束
               while((!(DH))&&flag++);
               flag=2;
               //判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
               while((DH)&&flag++);
               //数据接收状态
               COM();
               RH_data_H_temp=comdata;
               COM();
               RH_data_L_temp=comdata;  
               COM();
               T_data_H_temp=comdata;
               COM();
               T_data_L_temp=comdata;  
               COM();
               checkdata_temp=comdata;
               DH_HIGH();
                //数据校验
               temp=(T_data_H_temp+T_data_L_temp+RH_data_H_temp+RH_data_L_temp);
               if(temp==checkdata_temp)
               {   RH_data_H=RH_data_H_temp;
                    RH_data_L=RH_data_L_temp;  
                    T_data_H=T_data_H_temp;  
                    T_dataL=T_data_L_temp;  
                    checkdata=checkdata_temp;  
                }

          } //fi

}

void Delayms(uint ms)
{  uchar i;
    while(ms--)
    { for(i=0;i<120;i++);
     }
}

--------------下面为液晶模块程序--------
uchar LCD_Busy_Check()
{ uchar result;
   TRISB=0xFF;  
    LCD_RS = 0;
    LCD_RW = 1;
    LCD_EN = 1;
    Delayms(1);
    result=PORTB;
    LCD_EN=0;
    return result;
}

void Write_LCD_Command(uchar cmd)
{ while((LCD_Busy_Check()&0x80)==0x80);
    TRISB=0x00;
    LCD_RS = 0;
    LCD_RW = 0;
    LCD_EN = 0;
    PORTB=cmd;
    LCD_EN = 1;
    Delayms(1);
    LCD_EN = 0;
}

void Write_LCD_Data(uchar dat)
{ while((LCD_Busy_Check()&0x80)==0x80);
   TRISB=0x00;
   LCD_RS" = 1;
   LCD_RW = 0;
   LCD_EN = 0;
   PORTB = dat;
   LCD_EN = 1;
   Delayms(1);
   LCD_EN = 0;
}

void LCD_Initialise()
{ Write_LCD_Command(0x01);
   Delayms(1);
   Write_LCD_Command(0x38);
   Delayms(1);
   Write_LCD_Command(0x0c);
   Delayms(1);
   Write_LCD_Command(0x06);
   Delayms(1);
}

void Set_LCD_POS(uchar pos)
{
    Write_LCD_Command(pos|0x80);
}

void init()
{ ADCON1=0x07;  
   TRISA=0x00;
   TRISC=0x00;
}

void disp()
{  Set_LCD_POS(0x00);
    Write_LCD_Data(RH_data_H/10+0x30);
    Set_LCD_POS(0x01);
    Write_LCD_Data(RH_data_H%10+0x30);
    Set_LCD_POS(0x02);
    Write_LCD_Data('%');
    Set_LCD_POS(0x07);
    Write_LCD_Data(T_data_H/10+0x30);
    Set_LCD_POS(0x08);
    Write_LCD_Data(T_data_H%10+0x30);
    Set_LCD_POS(0x09);
    Write_LCD_Data(0xdf);
    Set_LCD_POS(0x0A);
    Write_LCD_Data(0x43);
}


void main()
{ init();
    LCD_Initialise();
    DH_HIGH();
    while(1)
     { RH();
        disp();
      }
}





DHT11说明书081206.pdf (677.52 KB)

相关帖子

沙发
tyw| | 2010-10-25 18:08 | 只看该作者
本帖最后由 tyw 于 2010-10-25 18:16 编辑

贴个DH11厂方范例,湿度采样10秒一次,数据应该不会跳的

51_DHT11 C51.rar (27.76 KB)


//****************************************************************//
//                 DHT21使用范例
//单片机 : AT89S52 或 STC89C52RC
// 功能  :串口发送温湿度数据 晶振 11.0592M 波特率 9600
//硬件连接: P2.0口为通讯口连接DHT11,DHT11的电源和地连接单片机的电源和地,单片机串口加MAX232连接电脑
// 公司  :奥松电子   
//****************************************************************//
#include <reg51.h>
#include <intrins.h>
//
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 ;
//----------------------------------------------//
//----------------定义区--------------------//
//----------------------------------------------//
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;
     while((!P2_0)&&U8FLAG++);
   Delay_10us();
      Delay_10us();
   Delay_10us();
     U8temp=0;
      if(P2_0)U8temp=1;
      U8FLAG=2;
   while((P2_0)&&U8FLAG++);
     //超时则跳出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;
  }
}
}

使用特权

评论回复
板凳
milktang|  楼主 | 2010-10-26 08:40 | 只看该作者
谢谢T叔,可我就是按照这个编写的啊,不知道哪里出了问题

使用特权

评论回复
地板
tyw| | 2010-10-26 09:18 | 只看该作者
本帖最后由 tyw 于 2010-10-26 12:25 编辑






使用特权

评论回复
5
yewuyi| | 2010-10-26 10:15 | 只看该作者
应该是SHT11吧!?

什么时候出现DHT11了?

使用特权

评论回复
6
milktang|  楼主 | 2010-10-26 10:50 | 只看该作者
查看校验和数据,温度和湿度数值加起来等于校验值,温度值恒定,但湿度值一直变动,所以校验值也一直变动,不知道为什么读前两个湿度字节一直跳变。

使用特权

评论回复
7
tyw| | 2010-10-26 12:32 | 只看该作者
湿度值在后面几个字节失步了,有可能是与模块的通讯中处于边缘,即读入时切入点不在脉宽的中部,见上面汇编中的波形说明.
适当调整一下延时.

使用特权

评论回复
8
milktang|  楼主 | 2010-10-26 16:13 | 只看该作者
调整过延时,刚上电显示40多,然后马上下降30多,在30多恒定了一下,又下降到20几,然后就在20几左右徘徊

使用特权

评论回复
9
milktang|  楼主 | 2010-10-27 13:01 | 只看该作者
已经搞定,谢谢各位老师指导!

使用特权

评论回复
10
tyw| | 2010-10-27 13:29 | 只看该作者
死马猫冰鸭?哈哈

使用特权

评论回复
11
yinbaocai1| | 2011-7-13 09:50 | 只看该作者
请问您是怎么解决的? 1# milktang

使用特权

评论回复
12
xmchendaying| | 2013-2-9 00:23 | 只看该作者

使用特权

评论回复
13
花开为谁| | 2017-5-10 17:32 | 只看该作者
我现在也遇到这这样的问题,这个要怎么解决呢

使用特权

评论回复
14
simonliu009| | 2017-5-11 11:17 | 只看该作者
别玩DHT11了,精度太差

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

10

主题

267

帖子

4

粉丝