qq335702318 发表于 2010-12-7 23:11:41

驱动国产温湿度探头 DHT11成功 发调试心得

终于调通DHT11希望走过的大虾大力拍砖哦!!

DHT的温度精度只有2℃ 湿度是±5%RH
http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_603038FB24TR.jpg


这只东西的引脚以及外形图:
<center>http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_603041XC3293.jpg



首先,DHT11是单总线传输数据
数据共40bit,也就是有5个字节:湿度整数+湿度小数+温度整数+温度小数+校验和
数据格式以16进制直接显示 比如 20℃时 温度整数是0x20
(原文件名:40bit数据格式.jpg)

沟通从复位开始,读取DHT11的时序是 复位+40bit数据
复位时序如下:
http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_603037PCFT82.jpg
(原文件名:复位时序.jpg)
复位没什么好说的,把握好时间就是


40bit数据是连续输出的,无论是“数据0”还是“数据1”都是DHT拉低总线然后拉高总线
-_-# 那怎么知道输出1还是输出0 ?
看时序图:
输出数据1的时序:
DHT拉低总线12~14us然后拉高总线116~118us
http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_603040R7SGLL.jpg
(原文件名:数据1.jpg)


输出数据0的时序:
DHT拉低总线12~14us然后拉高总线26~28us
http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_603039T0FX4P.jpg
(原文件名:数据0.jpg)


不难看出,只要“检测”出高电平维持的时间长短就ok了~~!
一般的做法是等DHT拉高总线后delay40us,如果DHT要返回0,这时候总线已经不是高电平了,因为输出数据0只需拉高总线最多28us而已
无错!!但用这个办法,我却调了两个晚上之久!!可能因为这个位置的延时时间比较严格,不好调。
最后我用
n=0;
while(DHT总线)
{
n++;
}
当高电平信号撤销以后,while循环退出,判断N的大小来推断是属于数据0还是数据1,因为高电平时间越长N越大
当然了,这里不加跳转的话万一DHT接触不良会导致死循环
另外比较高速的单片机需要保证N不会在高电平撤销前溢出


手机拍照不清晰,这是实物图:
http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_603043M7RLFJ.jpg
(原文件名:室温.jpg)

http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_603044MIY2A7.jpg
(原文件名:温度探头.jpg)

http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_603045HFFRSZ.jpg
(原文件名:哈一口气后.jpg)

http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_603046AT2SRA.jpg
(原文件名:哈一口气后.jpg)

http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_603047JSTUG5.jpg
(原文件名:哈一口气后.jpg)


DHT 程序:

===================================    头 文 件    ===========================================


#ifndef _DHT11_h_
#define _DHT11_h


/**********************************************/
/*             引脚定义               */
/**********************************************/
sbit DHT_bus = P1^4        ;


/**********************************************/
/*             函数声明               */
/**********************************************/
bit start_DHT11(void);          //开始
void read_DHT11(void);          //读取
void delay_20us(void);          //20us延时
void delay_ms(unsigned char m);          //N ms延时
bit check_sum(void);            //和校验

/**********************************************/
/*               宏定义                   */
/**********************************************/
#define HIGH 1
#define LOW0

/**********************************************/
/*             变量定义               */
/**********************************************/
#define DHT_timeover 5               //高电平维持时间,用于识别“数据0”和“数据1”


/**********************************************/
/*               结构体                   */
/**********************************************/
struct DHT_data
{
unsigned char DH_H;   //湿度整数
unsigned char DH_L;   //湿度小数
unsigned char T_H;      //温度整数
unsigned char T_L;      //温度小数
unsigned char Checksum; //校验和
}DHT_data;



#endif




======================================= DHT驱动 =============================================

#include "DHT11.h"



/**********************************************/
/*         开始 DHT11 温湿度计            */
/* 输入:无                                                           */
/* 输出:应答标志0:应答失败   1:应答成功*/
/**********************************************/
bit start_DHT11(void)
{
bit DHT_start;
DHT_start = 0;
DHT_bus = HIGH;
DHT_bus = LOW;    //拉低18ms以上
delay_ms(18);
DHT_bus = HIGH;
delay_20us();
delay_20us();   //拉高20~40us
while(!DHT_bus)
{
DHT_start = 1;
};//DHT应答,DHT拉低80us后拉高80us,然后开始传输数据
//数据(40bit)=8bit湿度整数+8bit湿度小数+8bit温度整数+8bit温度小数+8bit校验和
while(DHT_bus){};
return(DHT_start); //应答成功返回1
}


/**********************************************/
/*         读取 DHT11 温湿度计            */
/* 读取结果存在DHT_data结构体内               */
/* 输入:无         输出:无                */
/**********************************************/
void read_DHT11(void)
{
unsigned char m,n,timer_dht;
unsigned char *p;
p=&DHT_data.DH_H;
for(m=0;m<5;m++)
{
for(n=0;n<8;n++)
{
   while(~DHT_bus);    //DHT拉低12-14us表示1bit数据开始
   timer_dht=0x00;
   while(DHT_bus)          //随后DHT拉高总线,单片机通过高电平维持的时间判断“数据0”还是“数据1”
   {
                     //数据0维持26~28us高电平,数据1维持116~118us高电平
   timer_dht++;          //由于此处对延时时间的长度要求很高,所以采用另一种办法判断

   };
   if(timer_dht>DHT_timeover)
   {
   *p<<=1;
   *p|=0x01;
   }
   else
   {
   *p<<=1;
   *p&=0xfe;
   };
};
p++;
};
}

/**********************************************/
/*         20us 精 确 延 时               */
/* 51用在12Mhz晶振下                        */
/* 调用函数使用LCALL和RET指令,共花费4个周期*/
/* 因此只有16个NOP                            */
/**********************************************/
void delay_20us(void)
{
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
}


/**********************************************/
/*               N ms 延 时               */
/* while()额外占用约5周期                     */
/* 因此内层while(40--)20us 大约1ms            */
/* Nms延时函数(未测试)                        */
/**********************************************/
void delay_ms(unsigned char m)
{
unsigned char n = 38;
while(m--)
{
while(n--)
{
delay_20us();
};
};
}



/**********************************************/
/*         校验和判 断                */
/* 校验位 = 湿度整数位+湿度小数位+温度整数位+温度小数位 之和 */
/* 校验正确返回:1          失败返回:0      */
/**********************************************/
bit check_sum(void)
{
if(DHT_data.Checksum==(DHT_data.DH_H+DHT_data.DH_L+DHT_data.T_H+DHT_data.T_L))
return(1); //校验正确
else
return(0); //校验失败
}

(居中了..怎么左对齐这段文字?)

===================================================================================================================================
规格书ourdev_603049Q9F28W.pdf(文件大小:585K) (原文件名:DHT11规格书.pdf)
完整程序ourdev_603050D0DKZG.rar(文件大小:575K) (原文件名:DHT11.rar)

wkman 发表于 2010-12-7 23:42:05

嘿嘿,不是几年前有个 “小女子” 也共享了DHT11的源程序,,搜搜,

bxzyf 发表于 2010-12-8 00:05:18

我也用了DHT11,做了几个湿度测量仪拿去检测,人家告诉我:结果差的很!(大大超出5%)。这玩意是数字输出的,我的软件也没问题。
等侯楼主说说准确度。

abc220 发表于 2010-12-8 00:17:39

看到这个标题,第一时间想到的是“小女子”帖子。

ljt8015 发表于 2010-12-8 12:14:35

mark!~

tbbt 发表于 2011-2-22 21:41:26

LZ,最近在调DHT11,怎么返回的小数位都是0啊,效验和也是对的,不知道你们的是不是这样

ssaweee 发表于 2011-2-22 21:44:14

回复【2楼】bxzyf
-----------------------------------------------------------------------

用过,也觉得误差有点大。

gxy508 发表于 2011-2-23 15:10:12

mark

bxzyf 发表于 2011-2-23 15:49:55

回复【5楼】tbbt
lz,最近在调dht11,怎么返回的小数位都是0啊,效验和也是对的,不知道你们的是不是这样
-----------------------------------------------------------------------

小数位目前是0,预留的。数据手册里有说明。

843502 发表于 2011-2-23 18:57:32

温湿度还是模拟头线性好,而且抗腐蚀也要比数字头好。我也是初学正在做这个。。。。

sdwzq 发表于 2011-2-24 16:44:57

不错,记号,以后待研究!!谢谢共享

danceman_uk 发表于 2011-3-3 01:16:46

记号,DHT11在淘宝上7.8元. DHT90要38元.看来差别在精度上

bxzyf 发表于 2011-3-3 02:58:07

DHT90:
湿度测量精度:±4.5%RH,很一般啊。

benlippen 发表于 2011-3-3 09:07:47

mark

tonyone 发表于 2011-3-3 09:26:25

mark

aahui 发表于 2011-3-3 16:17:36

要顶一下

wpnx 发表于 2011-3-3 16:50:58

mark

hepday 发表于 2011-3-8 11:42:02

这程序到底能用么?

wanas 发表于 2011-3-8 11:45:33

mark

Pjm2008 发表于 2011-3-8 13:26:05

这种探头反应很慢,只用过三米长的传输距离。现在用AM2301-2303系列精度没测过,坏了三个,一个2303全新的,温度正常,湿度固定值,2301两个,一个数据线与地线接反了,另一个用着用着就坏了。国产在可靠性方面有待改进。

fay02 发表于 2011-3-8 21:20:51

MARK

danceman_uk 发表于 2011-3-9 01:59:56

回复【12楼】bxzyf
dht90:
湿度测量精度:±4.5%rh,很一般啊。
-----------------------------------------------------------------------

还有温度,适合范围.这些产品主是国内代理商垄断暴利了

lcmdw 发表于 2011-3-9 16:20:54

mark

gwh1128 发表于 2011-3-9 19:11:17

貌似国产的这些稳定度 跟 精度 都很难保证啊,SHT的卖那么贵看来是有道理的啊

13590955160 发表于 2011-4-4 11:36:07

看一看

20074698 发表于 2011-4-25 02:02:56

雪中送炭,这正是我毕业设计课题!!!!!!!!!

RRzihai 发表于 2011-5-10 19:34:28

楼主。。。如果温度整数是0x2e,那输出是多少啊??

qq335702318 发表于 2011-5-10 20:06:06

回复【26楼】RRzihai
-----------------------------------------------------------------------
没记错的话DHT11应该是直接输出BCD格式所以理论上不会出现0x2e这种数据

RRzihai 发表于 2011-5-10 20:53:21

回复【27楼】qq335702318 | 昌少
-----------------------------------------------------------------------
额。。可是真的出现了。。我看不懂数据手册里的一段话,
http://cache.amobbs.com/bbs_upload782111/files_39/ourdev_638883R15OD0.jpg
(原文件名:怎么求的啊??.jpg)
这个红框框里的是怎么求得的啊?

qq335702318 发表于 2011-5-10 21:46:44

回复【28楼】RRzihai
-----------------------------------------------------------------------

高位先出 :串行数据先输出高位数据位    .....、data bit4、data bit5>>>>>Send>>>>>data bit6、data bit7

关于数据格式:
0000 0010 +1000 1100+0000 0001 +0101 1111
——————————   ——————————
这里不是进行加法运算   这里不是进行加法运算
而是组合成:             而是合成:
0000001010001100         0000000101011111
换成十进制:652          换成十进制:351


关于校验和:
校验和是00000010 + 10001100+00000001 + 01011111这里是执行加法运算
自己用计算机敲一下就可以验证了

关于负值:
-10℃表示为10000000 01100100    即最高位为1时表示负值

anvy178 发表于 2011-5-11 09:43:36

标记下

RRzihai 发表于 2011-5-11 11:28:58

回复【29楼】qq335702318 | 昌少
-----------------------------------------------------------------------
谢谢昌少哥哇。。看懂啦。太神奇了。我怎么就没发现呢。

RRzihai 发表于 2011-5-11 11:42:38

回复【29楼】qq335702318 | 昌少
-----------------------------------------------------------------------

不过这个是DHT21的数据格式。。DHT11的数据格式都找不到哇。。我的DHT11输出的不是BCD格式,会有0x2e这种出现,那肯定需要再换算过。不知道如何换算啊。。奥松的手册都没写的。。

xinjie1023 发表于 2011-5-15 21:01:07

收藏。

yelanghada 发表于 2011-5-16 23:43:20

mark 一下

xytzc 发表于 2011-5-17 00:22:49

mark

fuwa 发表于 2011-5-17 18:24:12

想问下楼主大神,怎么用你的程序在1602上也还是不能显示数据啊?我原先是总是显示零?求解~~~

qq335702318 发表于 2011-5-17 19:24:29

回复【37楼】fuwa
-----------------------------------------------------------------------

试试把1602的忙判断用延时代替

yhl_wf 发表于 2011-5-19 14:23:53

这个我最近也调出来了,误差确实大
这里我想问问楼主,如果一个单片机上接两个,如何做?
这个是单总线么?我看只写了单总线数据模式
datasheet上也没说序列号的事?求解

qq335702318 发表于 2011-5-20 12:38:28

回复【39楼】yhl_wf
-----------------------------------------------------------------------

18B20有惟一ID号,可以使用二叉树算法去遍历,操作并联在同一条线上的某个器件。还带CRC校验
这个DHT11做不到
如果要使用几个DHT11,我觉得一个器件可能得使用一条IO口了

yhl_wf 发表于 2011-5-20 14:55:23

嗯,谢谢楼主耐心回答

yhl_wf 发表于 2011-5-20 17:01:20

为啥我单个好使,我控制两个就不好使?
一个用3.7一个用3.6.我菜鸟,麻烦楼主仔细讲一下
单个的时候可以连续读数,控制两个就不行,中间延时很长也不行

lixupeng 发表于 2011-5-20 17:55:20

mark!!

zhaoxukiller 发表于 2011-5-24 18:58:48

楼主你好,为什么我做完竟然出现了a-f   16进制数据?

heero 发表于 2011-5-24 23:18:36

不错,记号,以后待研究!!谢谢共享

fuwa 发表于 2011-5-27 14:41:18

不得不说这程序的时序令人很纠结~~~~~

heero 发表于 2011-5-27 16:10:16

楼主能说说原理吗??
我没接触过这方面的知识,能说说吗??
谢谢!!!

donglaile 发表于 2011-6-10 20:15:05

用proteus仿真,lcd无任何显示,下到单片机里lcd也无显示,郁闷。。。好像一进入read_DHT11()就出不来了,研究了一天也没弄懂
本人菜鸟,学mcu没多久,请见谅

467513422 发表于 2011-6-20 10:24:02

mark

hepday 发表于 2011-6-20 13:08:07

这个B程序我看只有用文档里的那个是没问题,楼主的程序我试过,会出现a-f.
肯定是有问题的,自己写的也不对的~

#include"DHT11.h"

unsigned charTemp;
/*---------------------------------
|函数名称:毫秒级延时函数。
|说    明:晶振12Mhz
|延时时间:1.01Ms
|调试说明:对于j我原定义成char型,怎么调试结果都不对,仿真发现只能延时30几US。
|         改成int型OK。
-----------------------------------*/
void        Delay_Xms(unsigned int Time)
{
                unsigned         int i = 0;
                unsigned    int j = 0;
                for (i = Time;i > 0;i--)
                        {
                                        for (j = 123;j > 0;j--);
                        }
}

/*-------------------------------
|MOV                R7,#0X01;                1
|LCALL          DELAY;                        2
|DELAY:          DJNZ R7,DELAY;        2
|RET                                                2

|延时时间 = 5+I*2;
|//这个计算公式还是蛮准确的
|(至少对于12M晶振)
---------------------------------*/
void        Delay_Us(unsigned char        i)
{
                while(--i);
}
/*---------------------------------
|函数名称:DHT11开始信号
|说    明:成功返回1,否则返回0
|输    入:无
|输    出:DHT_StarT
-----------------------------------*/
bit                DHT11_Read(void)
{
                bit                        Flag;
                unsigned char i                 = 0;
                unsigned char j                        = 0;
                unsigned char n         = 0;
                Flag                  = 0;
                DHT11_Dq = 1;
                DHT11_Dq = 0;
                Delay_Xms(300);
                DHT11_Dq = 1;
                Delay_Us(16);                              //拉高总线要20-40US,根据公式这里为35US
                while(!DHT11_Dq);                   //系统响应后要拉低总线80US
                while(DHT11_Dq){}               //系统响应后要拉高总线80US
                for (i = 0;i < 5;i++)
                        {
                                Temp = 0x00;
                                for(j = 0;j < 8;j++)
                                        {
                                               
                                                while(!DHT11_Dq); //数据的开始是L电平
                                                n = 0;
                                                while(DHT11_Dq)   //数据高电平
                                                        {
                                                                n++;
                                                        }
                                                if (n > 4)
                                                        {
                                                                Temp |= (0x80 >> j);
                                                        }
                                        }
                        }
                if (Temp == (Temp + Temp + Temp + Temp))
                        {
                                        Flag = 1;       
                        }
                return(Flag);
               
}

wcm_e 发表于 2011-6-20 13:28:25

mark

yinbaocai 发表于 2011-7-13 09:36:35

回复【44楼】zhaoxukiller 搁浅的夜
-----------------------------------------------------------------------

LED程序有问题

hepday 发表于 2011-7-18 22:49:14

我现在知道楼主为什么要2天了,其实之前的方法是对的,就是一个延时后需要等待的~

three_antenna 发表于 2011-7-19 10:00:54

不知为什么湿度计显示室内湿度为58%,而DHT11显示32%

qq335702318 发表于 2011-7-20 19:24:10

回复【54楼】hepday
-----------------------------------------------------------------------

2天??

brahen 发表于 2011-7-20 19:47:56

单总线协议?不是有专利的吗?

Pioneermcu 发表于 2011-7-20 20:58:08

刚刚有需要!

newhand1991 发表于 2011-8-4 23:41:35

呵呵,程序写复杂了。我上一段:
#include<reg52.h>
#include<intrins.h>
#include "lcm1602.h"

#define uchar unsigned char
#define uintunsigned int

sbit IO=P2^0;
sbit beep=P2^1;

void delay30ms()
{
       uchar i,j;
       for(i=60;i>0;i--)
       for(j=500;j>0;j--);
}

void main()
{
        uchar i,j,test,number=0,a,b,c,d,temp;
        uchar code num[]="0123456789";

        init_1602();
while(1)
{       
        IO=1;
    _nop_();_nop_();_nop_();_nop_();_nop_();
    IO=0;// 开始信号
    delay30ms();
    IO=1;        //开始信号结束
           for(i=20;i>0;i--);
        if(IO==0)
                beep=0;                 
        while(!IO);
        while(IO);        //等待开始传送信号       

        for(j=0;j<40;j++)
        {
                while(!IO);
                for(i=14;i>0;i--);
                if(IO==1)
                        temp|=0x01;
                while(IO);               
                number++;
                if(number==8)
                        {
                                a=temp;
                                temp=0;
                        }
                else if(number==16)
                        {
                                b=temp;
                                temp=0;
                        }
                else if(number==24)
                        {
                                c=temp;
                                temp=0;
                        }
                else if(number==32)
                        {
                                d=temp;
                                temp=0;
                        }
                else if(number==40)
                        {
                                test=temp;
                                temp=0;
                                number=0;
                        }               
                temp<<=1;                                                                       
        }       

       if(a+b+c+d==test)
       {          
          write_com(0x80+0x00);
          write_data(num);
          write_data(num);
          write_data(num);
          write_com(0x80+0x40);
          write_data(num);
          write_data(num);
          write_data(num);
          beep=1;
       }
       
       IO=1;
       delay_50us(1000);
}
}



其中的beep我是做测试指示的,就是说如果有采集,蜂鸣器就响一下。lcm1602.h是液晶1602的驱动程序ab cd 分别是第一、第二···个8位数据。看了资料的应该会很清楚。

myhonour 发表于 2011-8-5 14:05:03

mark

charles310 发表于 2011-8-31 16:28:34

mark

bingshuihuo888 发表于 2011-8-31 21:51:01

mark

gdutzl 发表于 2012-3-29 23:09:40

newhand1991 发表于 2011-8-4 23:41 static/image/common/back.gif
呵呵,程序写复杂了。我上一段:
#include
#include


可以在51单片机开发板上运行吗

newhand1991 发表于 2012-4-7 09:04:02

gdutzl 发表于 2012-3-29 23:09 static/image/common/back.gif
可以在51单片机开发板上运行吗

嗯,完全可以的,是我自己测试成功了的程序。

lryxr2507 发表于 2012-4-7 11:18:28

我的液晶万年历上正使用,感觉一般生活使用足够了,误差在可以接受范围内.

gdutzl 发表于 2012-4-7 12:29:47

newhand1991 发表于 2012-4-7 09:04 static/image/common/back.gif
嗯,完全可以的,是我自己测试成功了的程序。

能提供完整程序吗?

jetli 发表于 2012-4-7 14:06:44

看了ls各位的回复有收获,

一分钱一份货噢。

newhand1991 发表于 2012-4-7 14:49:14

60楼就是我完整的程序,就是没有1602液晶的驱动,其他的都有。

pro2013 发表于 2012-6-3 23:10:47

RRzihai 发表于 2011-5-10 19:34 static/image/common/back.gif
楼主。。。如果温度整数是0x2e,那输出是多少啊??

直接转化:46是不是啊?

stely 发表于 2012-6-3 23:12:43

支持楼主无私奉献

tepaiyuan 发表于 2012-6-3 23:43:14

学习啦!不错

jklooo 发表于 2012-6-27 12:49:28

温湿度计各种场合都用的比较多,正需要高温温湿度计。

SengChuary 发表于 2012-6-27 14:21:39

这个DHT11能配合数字时钟电路显示的就好了

lyg407 发表于 2012-6-28 13:43:49

不错。。。帮顶!

wtiechen1969 发表于 2012-6-28 20:23:16

如果要求不高还是很不错的,毕竟便宜嘛!

loyoid 发表于 2012-6-29 15:01:56

不错,记号,以后待研究!!谢谢共享

xinfeng 发表于 2012-6-29 15:07:02

mark备用

zengdz 发表于 2012-8-20 10:58:15

newhand1991 发表于 2011-8-4 23:41 static/image/common/back.gif
呵呵,程序写复杂了。我上一段:
#include
#include


果然精简,但很好用

zengdz 发表于 2012-8-20 10:59:50

zhaoxukiller 发表于 2011-5-24 18:58 static/image/common/back.gif
楼主你好,为什么我做完竟然出现了a-f   16进制数据?

这跟液晶显示的编码有关

cjt5132 发表于 2012-11-3 01:39:03

mark...............

lryxr2507 发表于 2012-11-3 17:43:20

这几天正调试DHT22,但结果跟SHT11(进口)比差太远了,同样环境下(同时用不同电源供电,相距不超过50mm)测量空气,DHT22温度高3度,适度误差3%左右,采集更新慢,对DHT有些失望(SHT11与水银温湿度计测量结果相同).

ddcchh 发表于 2012-11-21 11:21:51

我也是初学正在做这个

tianyuhui 发表于 2012-12-13 23:15:15

n=0;
while(DHT总线)
{
n++;
}
感谢,这个太受用了,用例程看时许弄了3个小时无果,找的你这个帖子问题一下子解决了,我用的是STC 1tcnt>100 为 1...

yyd1123CC 发表于 2012-12-18 13:54:08

楼主 我用的11.0592的晶振 改了半天延时也调不出来 请教下 主要改下哪的延时呢
页: [1]
查看完整版本: 驱动国产温湿度探头 DHT11成功 发调试心得