终于调通DHT11 希望走过的大虾大力拍砖哦!!
DHT的温度精度只有2℃ 湿度是±5%RH
这只东西的引脚以及外形图:
<center>
首先,DHT11是单总线传输数据
数据共40bit,也就是有5个字节:湿度整数+湿度小数+温度整数+温度小数+校验和
数据格式以16进制直接显示 比如 20℃时 温度整数是0x20
(原文件名:40bit数据格式.jpg)
沟通从复位开始,读取DHT11的时序是 复位+40bit数据
复位时序如下:
(原文件名:复位时序.jpg)
复位没什么好说的,把握好时间就是
40bit数据是连续输出的,无论是“数据0”还是“数据1”都是DHT拉低总线然后拉高总线
-_-# 那怎么知道输出1还是输出0 ?
看时序图:
输出数据1的时序:
DHT拉低总线12~14us然后拉高总线116~118us
(原文件名:数据1.jpg)
输出数据0的时序:
DHT拉低总线12~14us然后拉高总线26~28us
(原文件名:数据0.jpg)
不难看出,只要“检测”出高电平维持的时间长短就ok了~~!
一般的做法是等DHT拉高总线后delay40us,如果DHT要返回0,这时候总线已经不是高电平了,因为输出数据0只需拉高总线最多28us而已
无错!!但用这个办法,我却调了两个晚上之久!!可能因为这个位置的延时时间比较严格,不好调。
最后我用
n=0;
while(DHT总线)
{
n++;
}
当高电平信号撤销以后,while循环退出,判断N的大小来推断是属于数据0还是数据1,因为高电平时间越长N越大
当然了,这里不加跳转的话万一DHT接触不良会导致死循环
另外比较高速的单片机需要保证N不会在高电平撤销前溢出
手机拍照不清晰,这是实物图:
(原文件名:室温.jpg)
(原文件名:温度探头.jpg)
(原文件名:哈一口气后.jpg)
(原文件名:哈一口气后.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 LOW 0
/**********************************************/
/* 变 量 定 义 */
/**********************************************/
#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)
-----------------------------------------------------------------------
没记错的话DHT11应该是直接输出BCD格式 所以理论上不会出现0x2e这种数据
-----------------------------------------------------------------------
额。。可是真的出现了。。我看不懂数据手册里的一段话,
(原文件名:怎么求的啊??.jpg)
这个红框框里的是怎么求得的啊?
-----------------------------------------------------------------------
高位先出 : 串行数据先输出高位数据位 .....、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时表示负值
一周热门 更多>