基于DHT11的温度检测.docx
《基于DHT11的温度检测.docx》由会员分享,可在线阅读,更多相关《基于DHT11的温度检测.docx(20页珍藏版)》请在冰豆网上搜索。
基于DHT11的温度检测
西安邮电大学
温度测控与报警系统
课程设计报告书
系部名称
:
自动化学院
学生姓名
:
专业名称
:
测控技术与仪器
班级
:
1001班
时间
:
2013年4月8日至
2013年4月19日
温湿度测控与报警系统设计
1、设计要求:
以DHT11作为温度传感器,进行环境温湿度测试。
将结果显示在数码管或液晶屏上。
同时,设定温度上下限,当温度越限即报警。
二、设计方案分析
1、方案设计:
2、背景知识介绍:
(1)控制部分
控制部分是采用单片机STC89C52。
<1>STC89C52简介
STC89C52是一种带8K字节闪烁可编程可檫除只读存储器的低电压,高性能COMOS8的微处理器,俗称单片机。
该器件采用ATMEL搞密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。
单片机总控制电路如下图
<2>复位操作
复位操作有上电自动复位相按键手动复位两种方式。
上电自动复位是通过外部复位电路的电容充电来实现的,其电路如图所示。
这佯,只要电源Vcc的上升时间不超过1ms,就可以实现自动上电复位,即接通电源就成了系统的复位初始化。
按键手动复位有电平方式和脉冲方式两种。
其中,按键电平复位是通过使复位端经电阻与Vcc电源接通而实现的,其电路如图(b)所示;而按键脉冲复位则是利用RC微分电路产生的正脉冲来实现的,
其电路如下图所示:
(a)上电复位(b)按键电平复位(c)按键脉冲复位
上述电路图中的电阻、电容参数适用于6MHz晶振,能保证复位信号高电平持续时间大于2个机器周期。
本系统的复位电路采用上电复位方式。
(2)测量部分
测量部分我们采用DHT11温度传感器。
1>概述:
DHT11是广州奥松有限公司生产的一款湿温度一体化的数字传感器。
该传感器包括一个电阻式测湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。
通过单片机等微处理器简单的电路连接就能够实时的采集本地湿度和温度。
DHT11与单片机之间能采用简单的单总线进行通信,仅仅需要一个I/O口。
传感器内部湿度和温度数据40Bit的数据一次性传给单片机,数据采用校验和方式进行校验,有效的保证数据传输的准确性。
DHT11功耗很低,5V电源电压下,工作平均最大电流0.5mA。
性能指标和特性如下:
�工作电压范围:
3.5V-5.5V
�工作电流:
平均0.5mA
�湿度测量范围:
20-90%RH
�温度测量范围:
0-50℃
�湿度分辨率:
1%RH8位
�温度分辨率:
1℃8位
�采样周期:
1S
�单总线结构
�与TTL兼容(5V)
2>管脚排列如下:
3>应用电路连接说明
DHT11数字湿温度传感器连接方法极为简单。
第一脚接电源正,第四脚接电源地端。
数据端为第二脚。
可直接接主机(单片机)的I/O口。
为提高稳定性,建议在数据端和电源正之间接一只4.7K的上拉电阻。
第三脚为空脚,此管脚悬空不用。
●引脚说明:
Vcc正电源Dout输出NC空脚GND地
4>DHT11数据结构
●DHT11数字湿温度传感器采用单总线数据格式。
即,单个数据引脚端口完成输入输出双向传输。
其数据包由5Byte(40Bit)组成。
数据分小数部分和整数部分,具体格式在下面说明。
●一次完整的数据传输为40bit,高位先出。
●数据格式:
8bit湿度整数数据+8bit湿度小数数据
+8bit温度整数数据+8bit温度小数数据+8bit校验和
●校验和数据为前四个字节相加。
●传感器数据输出的是未编码的二进制数据。
数据(湿度、温度、整数、小数)之间应该分开处理。
如果,某次从传感器中读取如下5Byte数据:
byte4byte3byte2byte1byte0
0010110100000000000111000000000001001001
整数小数整数小数校验和
●湿度温度校验和由以上数据就可得到湿度和温度的值,计算方法:
humi(湿度)=byte4.byte3=45.0(%RH)
temp(温度)=byte2.byte1=28.0(℃)
jiaoyan(校验)=byte4+byte3+byte2+byte1=73(=humi+temp)(校验正确)
●注意:
DHT11一次通讯时间最大3ms,主机连续采样间隔建议不小于100ms。
5>DHT11的传输时序
5.1>DHT11开始发送数据流程
主机发送开始信号后,延时等待20us-40us后读取DH11T的回应信号,读取总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉高,准备发送数据,每一bit数据都以低电平开始,格式见下面图示。
如果读取响应信号为高电平,则DHT11没有响应,请检查线路是否连接正常。
5.2>主机复位信号和DHT11响应信号
5.3>数字‘0’信号表示方法
5.4>数字‘1’信号表示方法
(3)显示部分
1602采用标准的16脚接口,其中:
●第1脚:
VSS为地电源
●第2脚:
VDD接5V正电源
●第3脚:
V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度
●第4脚:
RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
●第5脚:
RW为读写信号线,高电平时进行读操作,低电平时进行写操作。
当RS和RW共同为低电平时可以写入指令或者显示地址,当RS为低电平RW为高电平时可以读忙信号,当RS为高电平RW为低电平时可以写入数据。
●第6脚:
E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。
●第7~14脚:
D0~D7为8位双向数据线。
●第15~16脚:
空脚
1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,如表1所示,这些字符有:
阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”
1602液晶模块内部的控制器共有11条控制指令,如表2所示
它的读写操作、屏幕和光标的操作都是通过指令编程来实现的。
(说明:
1为高电平、0为低电平)
●指令1:
清显示,指令码01H,光标复位到地址00H位置
●指令2:
光标复位,光标返回到地址00H
●指令3:
光标和显示模式设置I/D:
光标移动方向,高电平右移,低电平左移S:
屏幕上所有文字是否左移或者右移。
高电平表示有效,低电平则无效
●指令4:
显示开关控制。
D:
控制整体显示的开与关,高电平表示开显示,低电平表示关显示C:
控制光标的开与关,高电平表示有光标,低电平表示无光标B:
控制光标是否闪烁,高电平闪烁,低电平不闪烁
●指令5:
光标或显示移位S/C:
高电平时移动显示的文字,低电平时移动光标
●指令6:
功能设置命令DL:
高电平时为4位总线,低电平时为8位总线N:
低电平时为单行显示,高电平时双行显示F:
低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符
●指令7:
字符发生器RAM地址设置
●指令8:
DDRAM地址设置
●指令9:
读忙信号和光标地址BF:
为忙标志位,高电平表示忙,此时模块不能接收命令或者数据,如果为低电平表示不忙。
●指令10:
写数据
●指令11:
读数据
3、硬件设计:
4、软件设计:
(见附录)
5、测试数据及设计结果:
六、调试中出现的错误及解决方法
:
用Proteus仿真软件仿真的时候里面的器件符号里找不到DHT11,只能用DS18B20代替。
在电路调试方面,我们组四个人先把每一个外围电路的工作原理弄懂,对它的工作电压电流核实,然后我们在实验板上把实际的电路连接起来,加上实际的电源,一个一个的调试,发现它确实能够正常工作时在做下一步。
:
本次设计我主要是做软件部分,采用的是STC89C52单片机,该单片机的稳定性比较好,编程简单,功能易实现。
在本次设计的过程中,发现很多的问题,单片机课程设计重点就在于软件算法的设计,需要有很巧妙的程序算法,虽然以前写过几次程序,但我觉的写好一个程序并不是一件简单的事。
:
通过这次对数字温度计的设计与制作,让我了解了设计电路的程序,也让我了解了关于数字温度计的原理与设计理念。
要设计一个电路总要先用仿真,仿真成功之后才实际接线的。
但是最后的成品却不一定与仿真时完全一样。
因为,再实际接线中有着各种各样的条件制约着。
而且,在仿真中无法成功的电路接法。
在实际中因为芯片本身的特性而能够成功。
所以,在设计时应考虑两者的差异,从中找出最适合的设计方法。
通过这次学习,让我对各种电路都有了大概的了解,所以说,坐而言不如立而行,对于这些电路还是应该自己动手实际操作才会有深刻理解。
:
我做的焊接的工作,从这次的课程设计中,我真真正正的意识到,在以后的学习中,要理论联系实际,把我们所学的理论知识用到实际当中,学习单机片机更是如此,程序只有在经常的写与读的过程中才能提高,在焊接晶振电路时,没有注意两个电容的大小,导致程序烧进去却不工作,后来自己的检查后发现错误的根源,换了电容,数码管立马显示数据。
那刻真的很高兴。
附程序:
#ifndef__TOU_H__
#define__TOU_H__
#include
#include
#include
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
/**********1602宏定义**********
#defineLCD_SCREEN_ON0x0C//显示开
#defineLCD_SCREEN_OFF0x08//显示关
#defineLCD_CURSOR_ON0x0A//显示光标
#defineLCD_CURSOR_OFF0x0c//无光标
#defineLCD_C_FLASH_ON0x0f//有光标,光标闪动
#defineLCD_C_FLASH_OFF0x0e//有光标,光标不闪动
//进入模式设置指令
#defineLCD_AC_UP0x06//新数据后光标右移
#defineLCD_AC_DOWN0x04//新数据后光标左移
#defineLCD_S_MOVE_ON0x05//画面可平移
#defineLCD_S_MOVE_OFF0x04//画面不可平移
//设定显示屏或光标移动方向指令
#defineLCD_C_LEFT0x10//光标左移1格,且AC值减1
#defineLCD_C_RIGHT0x11//光标右移1格,且AC值加1
#defineLCD_CHAR_LEFT0x18//显示器上字符全部左移一格,但光标不动
#defineLCD_CHAR_RIGHT0x1C//显示器上字符全部右移一格,但光标不动*/
#defineLCD_DATAP0
/*****************1602端口定义**********/
sbitBF=P0^7;//忙碌标志位,,将BF位定义为P0.7引脚
//sbitRS=P2^4;
//sbitRW=P2^3;
//sbitEN=P2^2;
sbitRS=P2^6;
sbitRW=P2^4;
sbitEN=P2^0;
/*****************DHT11端口定义**********/
sbitDHT11=P3^4;
//sbitDHT11=P2^1;
//sbitBUZZ=P1^7;
sbitBUZZ=P2^3;
/****************全局变量声明***************/
externfloatF16T,F16RH;
/********LCD函数声明*******/
voidInit_Lcd(void);
voidLCD_write_str(ucharX,ucharY,uchar*s);
voidLCD_set_xy(ucharx,uchary);
voidLCD_en_write(void);
voidLCD_write_char(ucharcd,ucharab);
voidLCD_byte(ucharabc);
intLCD_value(ucharx,uchary,floatf);
voidDelay_ms(uintn);
voidDelay_us(ucharn);
/************DHT11函数声明************/
voidgetDHT11(void);
#endif
#include
ucharU8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;
floatF16T,F16RH;//用于最终读取的温湿度数据
floatF16T,F16RH;
//以下为延时函数
voidDelay_ms(uintn)
{
ucharj;
while(n--)
{
for(j=0;j<125;j++);
}
}
voidDelay_us(ucharn)//Nus延时函数精度±4us
{
n=n/2;
while(--n);
}
//读取数据
charCOM(void)
{
chari,U8temp,U8comdata;
for(i=0;i<8;i++)
{
while(!
DHT11);//表示读取的高电位延时大于20多us则读取的是1否则读取的是0
Delay_us(35);//通过U8FLAG可判断bit11显示数据的脉长
U8temp=0;
if(DHT11)
U8temp=1;
while(DHT11);
U8comdata<<=1;
U8comdata|=U8temp;
}
returnU8comdata;
}
//----以下变量均为全局变量--------
//----温度高8位==U8T_data_H------
//----温度低8位==U8T_data_L------
//----湿度高8位==U8RH_data_H-----
//----湿度低8位==U8RH_data_L-----
//----校验8位==U8checkdata-----
voidgetDHT11(void)
{
GO1:
DHT11=0;
Delay_ms(20);//主机拉低18ms
DHT11=1;//总线由上拉电阻拉高主机延时20us
Delay_us(60);//主机设为输入判断从机响应信号
if(!
DHT11)//判断从机是否有低电平响应信号如不响应则跳出,响应则向下运行//T!
{
while(!
DHT11);//waitDHTgotohigh
while(DHT11);//数据接收状态
U8RH_data_H=COM();
U8RH_data_L=COM();
U8T_data_H=COM();
U8T_data_L=COM();
U8checkdata=COM();
DHT11=1;//数据校验
if((U8T_data_H+U8T_data_L+U8RH_data_H+U8RH_data_L)!
=U8checkdata)
gotoGO1;
}
F16T=U8T_data_H+((float)U8T_data_L)/256;
F16RH=U8RH_data_H+((float)U8RH_data_L)/256;
//F16T=33;
}
//F16=(U8T_data_H*10+(float)U8T_data_L*10/256)/10;
#include
/*********************************************************
*名称:
LCD_write_char(ucharcd,ucharab)
*功能:
写指令或数据当写ab时应使cd=0当cd不为0则写cd且ab的赋值无效
*入口参数:
cd:
指令内容ab:
数据内容指令常量已在上面定义但一般不用
*出口参数:
无
*范例:
LCD_write_char(0,‘f’)
*************CD_set_xy*************/
voidLCD_write_char(ucharcd,ucharab)
{
Delay_us(20);
if(cd==0)
{
RS=1;//RS=1,写显示内容
LCD_byte(ab);
}
else
{
RS=0;//RS=0,写命令
LCD_byte(cd);
}
}
/****************************************************************************
*名称:
Init_Lcd()主函数调用
*功能:
Lcd初始化
*入口参数:
无
*出口参数:
无
*范例:
在主函数中直接调用
****************************************************************************/
voidInit_Lcd()
{
LCD_write_char(0x38,0);
Delay_ms
(1);
LCD_write_char(0x38,0);
Delay_ms
(1);
LCD_write_char(0x38,0);
Delay_ms
(1);
LCD_write_char(0x0c,0);
Delay_ms
(1);
LCD_write_char(0x06,0);
Delay_ms
(1);
LCD_write_char(0x0c,0);
Delay_ms
(1);
LCD_write_char(0x01,0);
Delay_ms
(1);
}
/****************************************************************************
*名称:
LCD_write_str(ucharX,ucharY,uchar*s)主函数调用
*功能:
在指定地址写一个字符串eg:
Y=0,1,2,3,4,5,6,7,8,9,10...15。
X=0,1。
*入口参数:
X:
横坐标Y:
纵坐标*s:
字符串首地址
*出口参数:
无
*范例:
LCD_write_str(1,1,uchar*s)
****************************************************************************/
voidLCD_write_str(ucharX,ucharY,uchar*s)
{
LCD_write_char(0,'');
LCD_set_xy(X,Y);//写地址
while(*s)//写显示字符
{
LCD_write_char(0,*s);
s++;
}
}
/****************************************************************************
*名称:
LCD_set_xy(ucharx,uchary)//写地址函数
*功能:
指定一个地址
*入口参数:
X:
横坐标Y:
纵坐标
*出口参数:
无
*范例:
LCD_set_xy(5,1)
*************CD_set_xy******************************************************/
voidLCD_set_xy(ucharx,uchary)
{
ucharaddress;
if(y==0)
address=0x80+x;
else
address=0xc0+x;
LCD_write_char(address,0);
}
/****************************************************************************
*名称:
LCD_en_write(void)
*功能:
液晶使能
*入口参数:
无
*出口参数:
无
*范例:
直接调用
*************CD_set_xy*******************************************************/
voidLCD_en_write(void)//液晶使能
{
_nop_();
EN=1;
_nop_();
EN=0;
}
/****************************************************************************
*名称:
LCD_byte(abc);
*功能:
写一个字符到orcalledonebytetoLCD中
*入口参数:
*出口参数:
无
*************CD_set_xy******************************************************/
voidLCD_byte(ucharabc)
{
RW=0;
EN=0;
LCD_DATA=abc;
LCD_en_write();
}
//在液晶中显示浮点数函数
intLCD_value(ucharx,uchary,floatf)
{
ucharstr[15];/不能定义为char*str,数组长度一定要大于浮点数的总位数
sprintf(str,"%.1f",f);//1表示小数位数小数太多自动四舍五入
LCD_write_str(x,y,str);
return0;
}
#include
voidmain(void)
{
Init_Lcd();
while
(1)
{
getDHT11();
LCD_