DHT11数字温湿度传感器

我们在第19章学习了单总线的数字温度传感器,本章介绍的是另外一个单总线器件——DHT11数字温湿度传感器。它的数据传输方式与DS18B20类似,同样是在单一的总线上实现数据的双向传输。DHT11温湿度传感器能提供温度及湿度的双重测量,其结果以数字的形式输出,即能保证精度,又能降低硬件成本,在实践中得到了广泛的应用。本章将重点介绍DHT11数字温湿度传感器的原理和驱动方法。

20.1

DHT11数字温湿度传感器的功能

DHT11数字温湿度传感器是一种能以数字方式输出的温湿度复合传感器,传感器内部由温敏电阻、NTC测温器件以及一个高性能8位微处理器构成,具有高集成度、超小体积和低功耗的特点。

20.1.1

DHT11的性能指标

DHT11数字温湿度传感器为4针单排引脚封装,采用单线制串行接口,信号传输距离可达20米以上。每片DHT11传感器在出厂前都在精确的湿度校验室中进行校准,并将校准系数保存在该传感器中,当传感器工作时会调用校准系数并自动修正输出结果,从而确保每个传感器具有标称的输出精度。使用DHT11数字温湿度传感器组建的温湿度模块如图20-1所示。

DHT11数字温湿度传感器的性能参数详见表20-1,引脚功能详见表20-2。

从表20-1中列出的性能指标上来看,DHT11数字温湿度传感器的温度测量精度远不及我们前面介绍的数字温度传感器DS18B20,但其湿度的测量精度是经实验室标定的,所以它作为湿度测量还是有很高的应用价值的。

20.1.2

DHT11的典型应用

使用ATmega32单片机驱动DHT11数字温湿度传感器的电路原理如图20-2所示。

DHT11数字温湿度传感器与DS18B20数字温度传感器类似,采用的都是单总线的数据传输形式,传感器的第二脚是数据端,需要与单片机的I/O口相连接,数据端使用一个阻值约为5kΩ的上拉电阻上拉到Vcc。当控制器与DTH11的通信距离大于20米时,需要适当减小上拉电阻的阻值,以确保总线上数据传输的正确性。另外,用于数据传输的信号线质量会影响通信的距离和质量,因此在长距离传输时应该考虑使用高质量的屏蔽电缆。

DHT11数字温湿度传感器上电后,要经过1秒钟的稳定时间,在此期间微处理器无需发送任何指令。为提高测量精度和增加抗干扰性,可以在传感器的电源引脚和地之间并联一个100nF的电容(图中未画出)用于电源的退耦。

20.1.3

DHT11的通信时序

DHT11数字温湿度传感器采用单总线数据传输格式,每次通信时间约为4ms,一次完整的数据传输包含40个数据位。总线上数据高位在前,低位在后,其温度与湿度值均由整数部分和小数部分构成。DHT11数字温湿度传感器的数据格式如图20-3所示。目前版本的DHT11传感器输出温湿度的小数部分没有定义,读为零。当总线上数据正确传送时,校验和是将8bit湿度整数数据、8bit湿度小数数据、8bit温度整数数据和8bit温度小数数据相加后所得结果的末8位。

当控制器发送一个开始信号后,DHT11从低功耗模式转换到高速模式。在接收到控制器发送的开始信号后,DHT11发送响应信号,并送出40bit的数据,同时触发一次信号采集,之后DHT11会转换到低速模式并进入到待机状态。如果DHT11没有接收到开始信号,它不会主动进行温湿度采集。DHT11的数据通信过程如图20-4所示。

DHT11的数据通信过程可以归纳为以下几个步骤:

1)控制器发送开始信号。总线在空闲状态时为高电平,在数据传输开始时,控制器把总线拉低并保持低电平时间大于18ms,之后控制器释放总线,延时20~40μs,等待DHT11做出响应。此时控制器需要切换到输入模式,以便读取DHT11的响应信号,这时总线会由上拉电阻拉高。

2)DHT11响应开始信号。DHT11接收到控制器的开始信号后,发送一个80μs的低电平作为响应信号,之后释放总线80μs,总线被上拉电阻拉高,DHT11开始准备发送数据。

3)DHT11输出数据。DHT11输出的每一个数据位都是以50μs低电平时隙开始,随后的高电平存在时间决定了该数据位表示的是“0”还是“1”。当最后一个数据位传送完毕后,DHT11拉低总线50μs,随后总线由上拉电阻拉高进入空闲状态。DHT11输出数字信号“0”和“1”的时序分别如图20-5和图20-6所示。

20.2

DHT11的编程应用

为了验证DHT11数字温湿度传感器的功能,我们要使用AVR系统板构建一款数字式湿度计。按照图20-2所示的DHT11典型应用电路,搭建传感器单元电路,并将其与AVR系统板进行正确的连接。本书为了简化过程,使用了成品湿度传感器模块,但模块的原理与图20-2所示电路完全相同。硬件连接好后,打开Atmel Studio 6.1软件,新建名为DHT11的项目,保存在chapter20文件夹下,软件会自动将名为DHT11.c的源文件添加到新建的项目中。编辑DHT11.c源文件,具体代码详见代码清单20-1。

代码清单20-1

数字式湿度计

/*

*

DHT11.c *

PD4

连接DATA 端

*

Created: 2013/8/20

21:27:56

*

Author: GAO */

#include 
//
包含AVR 单片机头文件
#define F_CPU 16000000UL //
定义系统时钟频率
#include 
//
包含延时函数头文件
#define DATA_SET (PORTD|=0x10)
//
置位PD4
(DATA 线)
#define DATA_CLR (PORTD&=0xEF)
//
清零PD4
unsigned char table0[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f }; //
共阴无点
unsigned char table1[]={0xbf,0x86,0xdb,0xcf,0xe6, 0xed,0xfd,0x87,0xff,0xef }; //
共阴有点
unsigned char DHT_DATA[]={0,0,0,0,0}; //
定义数组存储从DHT11
中读取的数据
void display(void); //
数码管显示函数声明
unsigned char read_1byte(void)
; //
读取1byte 数据函数声明
void read_DHT11(void); //
读取DHT11
数据函数声明
int main(void)
{
DDRA=0xFF; //
设数码管段驱动端为输出
DDRB=0xF0; //
设数码管位驱动端为输出
DDRD=0x10; //
将PD4
设为输出(DATA 线)
while(1)
{
read_DHT11(); //
读取DHT11
数据
display()
; //
显示读取的数据
}
}
/**********
数码管显示函数**********/
void display(void)
{
unsigned char NUM4,NUM3,NUM2,NUM1; NUM1=DHT_DATA[0]%10; NUM2=DHT_DATA[0]%100/10; NUM3=DHT_DATA[2]%10; NUM4=DHT_DATA[2]%100/10; PORTA=table0[NUM1]; PORTB=0x10; _delay_ms(2); //
延时2ms PORTA=0x00; PORTB=0x00; _delay_ms(1); //
延时1ms PORTA=table0[NUM2]; PORTB=0x20; _delay_ms(2); //
延时2ms PORTA=0x00; PORTB=0x00; _delay_ms(1); //
延时1ms PORTA=table1[NUM3]; PORTB=0x40; _delay_ms(2); //
延时2ms PORTA=0x00; PORTB=0x00; _delay_ms(1); //
延时1ms PORTA=table0[NUM4]; PORTB=0x80; _delay_ms(2); //
延时2ms PORTA=0x00; PORTB=0x00; _delay_ms(1); //
延时1ms }
/**********
读取1byte 数据函数**********/
unsigned char read_1byte(void)
{
unsigned char i,TEMP; TEMP=0; for(i=0;i<8;i++)
{
while((PIND&0x10)==0); //50
μs 低电平期间程序在此等待
_delay_us(35); //
延时35
μs 跃过表示0
的高电平时间
TEMP=TEMP<<1; if((PIND&0x10)==0x10)
//
读取DATA 线,判断如果是1
{
TEMP=TEMP|0x01; //
给TEMP 最低位或1
}
while((PIND&0x10)==0x10); //
总线高电平期间程序在此等待
}
return TEMP; //
将读取的数据返回
}
/**********
读取DHT11
数据函数**********/
void read_DHT11(void)
{
unsigned char j; DDRD=DDRD|0x10; //PD4
设为输出
DATA_SET; //PD4
置1
DATA_CLR; //PD4
清零产生起始信号
_delay_ms(20); //
延时20ms ,控制器拉低总线至少18ms DATA_SET; //PD4
置1
_delay_us(30); //
控制器将总线拉高保持20~40
μs DDRD=DDRD&0xEF; //PD4
设为输入
PORTD=PORTD&0xEF; //
关闭PD4
引脚上拉电阻
if((PIND&0x10)==0)
//
如果控制器检测到DHT11
的低电平响应信号
{
while((PIND&0x10)==0); //DHT11
拉低总线时程序在此等待
while((PIND&0x10)==0x10); //DHT11
释放总线时程序在此等待
for(j=0;j<5;j++)
{
DHT_DATA[j]=read_1byte(); //
读取DHT11
的40bit 数据
}
}
}
/**********
结束**********/
成功编译以上代码后,将其下载到AVR系统板中,程序运行后的效果如图20-7所示。AVR系统板上数码管的显示数值即为当前环境的湿度值。不仅如此,我们只要将以上的程序稍加修改,就能实现温度和湿度同时读取和分屏显示的功能,毕竟湿度和温度这两个物理量在很多应用中是相关联的。

 


评论: