找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5028|回复: 0
打印 上一主题 下一主题
收起左侧

51单片机+DHT11的恒温控制系统资料+程序

[复制链接]
跳转到指定楼层
楼主
ID:702467 发表于 2020-5-12 18:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
   温度和湿度是两个基本的环境参数。在我们的生活中,我们要时刻关心环境的变化,只有很好的把握好环境的差异变化,我们才能更好的生存与发展。比如说在一些养殖厂,牲畜的成长,和温湿度是离不开的,它们只有在适宜的环境下,在适宜的温度和湿度下,才能成长的更快,我们才能获取更大的效益。准确测量温湿度在生物药学、食品加工、造纸业等行业更是至关重要。总之,无论在日常生活中还是在工业、农业方面都离不开对周围环境温湿度的测量。因此,研究温湿度的控制和测量具有非常重要的意义。
由于传感器能将各种物理量、化学量和生物量等信号转变为电信号,使得人们可以利用计算机实现自动测量、信息处理和自动控制。传感器主要用于测量和控制系统,它的性能好坏直接影响系统的性能。因此我们必须掌握各种传感器的结构、原理及其性能指标,通过对传感器实例的分析了解,才能将传感器和信息通信和信息处理结合起来,适应传感器的生产、研制和开发及应用。温湿度传感器发展速度快,应用领域也很广泛,并且还有很大发展潜力,为了提高对传感器的认识和了解,尤其是对温湿度传感器的深入研究,基于实时、准确和广泛的原则进行了设计。
本文设计的是基于单片机AT89C51的温湿度检测和控制系统,主要以广泛应用的DHT11温湿度传感器作为温度和湿度数据的采集,该传感器具有测量精度高、硬件电路简单、数据传输方便,可测试不同环境温湿度的特点。另外和控制电路相连,可以进行阈值的控制,使温度和湿度参数在预先设定的范围内,不需要人的直接参与。

空气中的水蒸汽吸附在感湿材料上后,元件的阻抗、介质常数发生很大的变化,从而制成湿敏元件。近年来,国内外在湿度传感器研发领域取得了较大的发展。湿敏传感器正从简单的湿敏元件向集成化、智能化、多参数检测的方向迅速发展。国内外各厂家的湿度传感器产品水平不一,质量价格都相差较大,用户如何选择性能价格比最优的理想产品确有一定难度,需要在这方面作深入的了解。现在国内市场上出现了不少国内外湿度传感器产品,电容式高分子聚合物,氯化锂和金属氧化物。
    测量温湿度的关键是温湿度传感器。过去测量温度与湿度是分开的。随着技术的进步和人们生活的需要出现了温湿度共测的传感器。温度传感器的发展经历了3个阶段:传统的分立式温度传感器、模拟集成温度传感器、智能集成温度传感器。目前,国际上新型温度传感器正从模拟式向数字式、从集成化向智能化、网络化的方向发展。温湿度传感器也是经历了这样一个阶段逐渐走向数字智能化。
温湿度检测系统在国内各行业的发展水平仍然不高,虽然应用已经十分广泛,但从国内生产的温湿度检测器来讲发展水平仍然不高,同日本、美国、德国等先进国家相比,仍然有着较大的差距。
进入21世纪后,特别在我国加入WTO后,国内产品面临巨大挑战。各行业特别是传统产业都急切需要应用电子技术、自动控制技术进行改造和提高。例如纺织业,温湿度是影响纺织品质量的重要因素,但纺织企业对温湿度的控制手段仍很粗糙,十分落后,绝大多数仍然在使用干湿球温度计,采用人工观测,人工调节阀门、风机的方法,其控制效果可想而知。制药行业里也基本如此。在食品行业里,则基本上凭经验,很少有人使用温湿度传感器。
1.3 设计的市场现状分析
纵观市场,温湿度检测技术已经比较成熟,已有的各种温湿度检测产品,五花八门,如A2000家用温湿度报警表、YD-808A工业用温湿度显示器等产品。 从功能上分析这些产品可以看出,一个比较完整的环境温湿度检测系统应该具备以下主要的三个功能:
   (1)实时检测出环境中的温度和湿度参数;
   (2)检测的参数值显示在显示设备上(如数码管,液晶显示器等);
   (3)根据环境要求,设定温度湿度报警的上下限值,并实时报警。
因此,本设计也应该具备这些功能,并且对每一个部分进行优化设计,也可以扩展系统功能。
除了功能上的分析之外,再看这些产品还存在一个问题就是价格太高,不符合普通消费者的消费水平,如A2000家用温湿度报警表,售价300元左右。
    综上所述,本设计设计出的环境温湿度检测系统,除了具备市场上已有产品的功能之外,还应该尽量降低制作价格。
1.4 温湿度检测技术和存在的问题
传统的温度和湿度检测系统主要有以下几种:
   (1)水汽压(e):是水汽在大气总压力中的分压力。它表示了空气中水汽的绝对含量的大小,以毫巴为单位;
   (2)相对湿度(rh):湿空气中实际水汽压e与同温度下饱和水汽压E的百分比,相对湿度的大小能直接表示空气距离饱和的相对程度。空气完全干燥时,相对湿度为零。相对湿度越小,表示当时空气越干燥。当相对湿度接近于100%时,表示空气很潮湿,越接近于饱和;
   (3)露点(或霜点)温度:指空气在水汽含量和气压都不改变的条件下,冷却到饱和时的温度;
   (4)干湿球温度表:用一对并列装置的、形状完全相同的温度表,一支测气温,称干球温度表,另一支包有保持浸透蒸馏水的脱脂纱布,称湿球温度表;
   (5)发湿度表(计):利用脱脂人发(或牛的肠衣)具有空气潮湿时伸长,干燥时缩短的特性,制成毛发湿度表或湿度自记仪器,它的测湿精度较差,毛发湿度表通常在气温低于-10℃时使用;
   (6)电阻式湿度片:利用吸湿膜片随湿度变化改变其电阻值的原理,常用的有碳膜湿敏电阻和氯化锂湿度片两种。前者用高分子聚合物和导电材料碳黑,加上粘合剂配成一定比例的胶状液体,涂覆到基片上组成的电阻片;后者是在基片上涂上一层氯化锂酒精溶液,当空气湿度变化时,氯化锂溶液浓度随之改变从而也改变了测湿膜片的电阻;
   (7)薄膜湿敏电容:是以高分子聚合物为介质的电容器,因吸收(或释放)水汽而改变电容值。它制作精巧,性能优良,常用在探空仪和遥测中。
随着智能检测系统的飞速发展,基于单片机的温湿度检测系统将多传感器系统结合在一起。如何把多传感器集中于一个检测控制系统,综合利用来自多传感器的信息,获得对被测对象的可靠了解和解释,以利于系统做出正确的响应、决策和控制,是智能检测控制系统中需要解决的首要问题。在温湿度要求严格的场合,利用多传感技术可以提高系统的可靠性和精度,亦可以提高系统的时间空间的覆盖范围。
1.5 设计内容和预期结果
1.5.1 主要完成内容
本文主要完成的内容有:
(1) 确定系统的总体功能设计方案;
(2) 完成总体设计方案原理图的绘制;
(3) 完成硬件电路的焊接及调试;
(4) 完成软件系统的设计及编译。
1.5.2 本文的设计思路
本文的设计目的是要对空气中的温度和湿度进行检测。系统的数据采集部分是温湿度传感器完成的,温湿度传感器将采集到的数据送入AT89C51单片机中,然后通过液晶显示器LCD1602进行显示,单片机将预设的参考值与测量值进行比较,根据比较结果作出判断,当温湿度值超过允许的误差范围,系统将发出报警声音。
(1)系统硬件设计
通过比较,选用AT89C51单片机来构造本系统。在设计过程当中,单片机的P0口用于液晶LCD1602显示, P3.4、P3.5、P3.6、P3.7为独立式键盘接口,P1.0口接温湿度传感器DHT11,P2.4口连接蜂鸣报警器。
(2)系统模块设计
测控模块:检测所处环境的温湿度数据。显示模块:温度和湿度采用液晶显示,分两行显示使测量结果更直观,便于管理人员做出决策。报警模块:系统采用三极管驱动的蜂鸣音报警,当温湿度超过系统所设置的阈值时,蜂鸣器就会发生报警。键盘模块;键盘采用的是独立式键盘,可分别设置温度和湿度的上限值。
1.5.3 预期结果
根据设计方案及思路,预测出现的设计结果,当系统完好的设计完后,连接所有的硬件设备,运行相应的软件设备。
软硬件连接完好,电路完善的情况下,肉眼能看到的是经过一系列的软硬件编译过的在LCD液晶显示器上显示的数字,当液晶显示器显示的温湿度值超过了预定的值时系统发出报警提示,当温湿度值没有超过预定的温湿度范围,测系统接收下一次的温湿度采集值。

2  温湿度测量系统方案设计
2.1系统总体设计
系统要完成的设计功能如下:
(1)实现对环境温湿度参数的实时采集,由单片机对数据进行循环检测、数据处理、显示,实现温湿度的连续测量;
(2)实现超限数据的及时报警;
(3)现场检测设备应具有较高的灵敏度、可靠性、抗干扰能力;
(4)软件设计既要具有完成数据采集、处理的功能,其软件编程应具有功能强大、界面友好、便于操作和执行速度快。
设计要达到的技术指标:
(1)测量范围: 湿度20-90%RH, 温度0-50℃;                  
(2)测量精度: 湿度±5%RH, 温度±2℃;                                           
(3)分 辨 率: 湿度1%RH, 温度1℃。
(4)测量数据无线上传到手机进行显示。
    该设计的总体方案是数据采集用的是DHT11温湿度传感器,它是一款含有已校准数字信号输出的温湿度复合传感器,传感器包括一个电阻式感湿元件和一个NTC测温元件,具有品质卓越、超快响应、抗干扰能力强、性价比极高等特点。单片机采用AT89C51,液晶显示采用LCD1602,报警采用蜂鸣器,键盘使用独立键盘,外加复位电路和时钟电路,测量数据无线上传串口WIFI模块。
温度湿度信号通过温湿度传感器进行信号的采集并转换成数字信号,再运用单片机AT89C51进行数据的分析和处理,并在LCD1602上显示当前温湿度。外加复位电路、时钟电路、键盘电路和报警电路。系统程序主要包括数据采集程序、温温度阈值设置程序、报警程序及显示程序等。本设计可以通过键盘手动设置温度湿度的上、下限值,该设定值为系统阈值。温湿度传感器将检测到的值传输给单片机,通过分析比较,当检测数值超出阈值时,驱动蜂鸣器报警,以便管理人员及时切断电源,实现系统的保护。

2.2 系统设计原则
要求单片机系统应具有可靠性高、操作维护方便、性价比高等特点。设计原则有以下几个:
(1)可靠性高 可靠性是单片机系统应用的前提,在系统设计的每一个环节,都应该将可靠性作为首要的设计准则。提高系统的可靠性通常从以下几个方面考虑:使用可靠性高的元器件;设计电路板时布线和接地要合理;对供电电源采用抗干扰措施;输入输出通道抗干扰措施;进行软硬件滤波等。

温度、湿度设置参数断电保存模块

电路选择了AT24C01电路作为温度、湿度参数的储存电路。AT24C01是美国Atmel公司的低功耗CMOS型E2PROM,内含256×8位存储空间,具有工作电压宽(2.5~5.5 V)、擦写次数多(大于10000次)、写入速度快(小于10 ms)、抗干扰能力强、数据不易丢失、体积小等特点。而且他是采用了I2C总线式进行数据读写的串行器件,占用很少的资源和I/O线,并且支持在线编程,进行数据实时的存取十分方便。AT24C01中带有的片内地址寄存器。每写入或读出一个数据字节后,该地址寄存器自动加1,以实现对下一个存储单元的读写。所有字节均以单一操作方式读取。为降低总的写入时间,一次操作可写入多达8个字节的数据。I2C总线是一种用于IC器件之间连接的二线制总线。他通过SDA(串行数据线)及SCL(串行时钟线)两根线在连到总线上的器件之间传送信息,并根据地址识别每个器件。 AT24C01正是运用了I2C规程,使用主/从机双向通信,主机(通常为单片机)和从机(AT24C01)均可工作于接收器和发送器状态。主机产生串行时钟信号(通过SCL引脚)并发出控制字,控制总线的传送方向,并产生开始和停止的条件。无论是主机还是从机,接收到一个字节后必须发出一个确认信号ACK。AT24C01的控制字由8位二进制数构成,在开始信号发出以后,主机便会发出控制字,以选择从机并控制总线传送的方向。
管脚描述:
●  SCK 为串行时钟:
    串行时钟输入管脚用于产生器件所有数据发送或接收的时钟这是一个输入管脚。
● SDA 为串行数据/地址:
双向串行数据/地址管脚用于器件所有数据的发送或接收SDL,是一个开漏输出管脚可与其它开漏输出或集电极开路输出进行线。
●  A0、A1、A2 为器件地址输入端:
当使用24C02 时最大可级联8个器件,如果只有一个24C01被总线寻址,这三个地址输入脚A0、A1、A2可悬空或连接到Vss。
● WP为写保护:
如果WP 管脚连接到Vcc 所有的内容都被写保护只能读当WP, 管脚连接到Vss 或悬空,允许器件进行正常的读/写操作。管脚图如图3-3所示。

特点:
内建128x8存储序列
2线制串行接口
双向数据传送协议
100kHz(1.8V,2.5V,2.7V) 和400kHz(5V)兼容
写同步时钟(最大10ms)
高可靠性
-极限:1M写时钟周期
-数据保存:100年
AT24C01提供电可擦除的串行1024位存储或可编程只读存储器(EEPROM)128字(8位/字)。
芯片在低压的工业与商业应用中进行了最优化。AT24C01的封装为8脚PDIP、8脚JEDEC
SOIC、8脚TSSOP,通过2线制串行接口进行数据传输。
设备操作: SDA管脚通常外部要拉高。SDA管脚上的数据只能在SCL低期间改变。数据在SCL高期间改变定义为一个开始或停止信号。
开始状态:在任何操作之前必须有一个开始信号----在SCL为高时SDA上产生一个下降沿。
停止状态: SCL为高时SDA产生一个上升沿是停止信号,停止信号后将停止所有通信。
在一个读的序列之后,停止信号将让EEPROM进入备用电源模式。

3.8报警模块及温度湿度控制模块

本系统采用蜂鸣器作为报警装置,蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。 蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。蜂鸣器在电路中用字母“H”或“HA”(旧标准用“FM”、“LB”、“JD”等)表示。

3.8.1蜂鸣器报警原理及温度湿度控制模块原理

本设计采用蜂鸣音报警电路,其工作过程就是把传感器采集的数据通过单片机处理后,与该参数上限给定值进行比较,如果高于上限值则进行报警。同时当温度,湿度低于设计值时,自动启动加温电、加湿设置进行加温、加湿工作。
蜂鸣器发声原理是电流通过电磁线圈,使电磁线圈产生磁场来驱动振动膜发声的,因此需要一定的电流才能驱动它,单片机I/O口引脚输出的电流较小,单片机输出的TTL电平基本上驱动不了蜂鸣器,因此需要增加一个电流放大的电路。所以才用一个三极管来放大驱动蜂鸣器。在本系统中峰鸣器报警接口电路的设计采用压电式蜂鸣器,通过AT89C51的1根I/O口线经驱动器驱动蜂鸣音发声。压电式蜂鸣器约需10mA的驱动电流,可以用一个晶体三极管驱动,P2.4接晶体管基极输入端。当P2.4输出高电平“1”时,晶体管导通,压电蜂鸣器两端获得约+5V电压而鸣叫;当P2.4输出低电平“0”时,三极管截止,蜂鸣器停止发声。

3.8.2 报警电路接口

声光报警系统由一个电阻R2,一个三极管BG1和一个蜂鸣器BY以及发光二极管D5与限流电阻R10组成,三极管用来放大电路中的电流,来驱动蜂鸣器发声,在发声的同时发光二极管D5闪亮。报警系统连接单片机的I/O口P2.3,当单片机检测到温度或者湿度超出所设置的阈值时,就会给P2.3置低电平0,这时三极管导通,蜂鸣器报警,如果没有超出阈值,P2.3置高电平1,三极管截止。R4与D1组成温度过低的报警指示电路及启动加温控制指示电路,温度低于温度设置下限值时,D1点亮,同时P1.7脚由高电平变为低电平,经R9、BG3驱动继电器工作,电机M2转动(用来模拟加热电器及加热通风机工作),当温度高于下限值时,D1O熄,同时M2停止工作。R5与D2组成温度高报警电路,温度高于上限值时,D2点亮。R6与D3组成湿度过低的报警指示电路及启动加湿水泵控制指示电路,R7、D4组成湿度高的报警指示电路,当湿度低于设置下限值时,D3点亮,同时P1.6脚由高电平变为低电平,经R8、BG2驱动继电器工作,电机M1转动(用来模拟加湿水泵工作),当湿度高于下温度下限值时,D3熄灭,这时水泵继续工作,当湿度高于湿度设置上限值时,D4点亮,同时停止加湿水泵工作。报警模块及加湿模块电路图如图3.12所示。

图3.12报警电路及加湿加温电路模块

3.9供电电路

整个湿度温度测量装置的供电设计采用5伏直流电源进行供电,图中C1,C2作为电源滤波电容。供电电源可以直接选用目前市面上比较多的手机充电电源作为供电电源,这种电源工作可靠,安全适用,成本低。

3.9小结

本系统设计主要有主控模块、显示模块、温湿度采集模块、WIFI串口通信模块、键盘模块、报警模块、复位电路和时钟电路八大模块。其中主控模块AT89C51的晶振电路采用12MHz的无源晶振,微调电容大小取22pF。显示模块选用LCD1602字符型液晶模块,是目前工控系统中使用最为广泛的液晶屏之一。温湿度采集模块所采用的DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与稳定性;其单线制串行接口,使系统集成变得简易快捷。报警模块采用蜂鸣器,采用PNP型晶体管9012放大单片机I/O口的电流。系统的输入模块采用独立式键盘,操作简单,温湿度检测方便准确。该设计最终要实现的目标是,温湿度采集数据并传输到单片机,单片机经过数据处理在发送到液晶显示器显示,同时单片机会将采集到的数据同系统设置温度、湿度值进行比较,如果超过定值,报警电路就会发出报警声光信号,如果温度、湿度在设置范围内,单片机就会继续采集温湿度数据。            
键盘一共有四个键,开关K1、K2、K3、K4分别接单片机的I/O口P3.4、P3.5、P3.6 、P3.7。K1是模式选择键,用来选择温度、湿度上下限值。K2和K3分别为设置温度、湿度上下限值, K4为保存键,设置完成按下该键后储存设置参数。显示器一共是两行显示,第一行显示的是温度,第二行显示的是湿度。
在完成了系统硬件的设计后,再设计系统软件,首先要建立程序框架的流程图,对整个设计划分模块,逐个模块实现其功能,最终把各个子模块合理的连接起来,构成总的程序,这样能快速准备的进行编程。首先建立主程序框架流程图,弄明白整个系统程序设计,其次再分别设计显示模块、传感器模块和键盘模块的程序,最后在进行整合,形成一个完整的程序。
本系统采用C语言编程。C语言是一种计算机程序设计语言。它既具有高级语言的特点,又具有汇编语言的特点。
C语言编程的优点有:
(1)简洁紧凑、灵活方便。C语言一共只有32个关键字,9种控制语句,程序书写形式自由,区分大小写。把高级语言的基本结构和语句与低级语言的实用性结合起来。C 语言可以像汇编语言一样对位、字节和地址进行操作,而这三者是计算机最基本的工作单元。   
(2)运算符丰富。C语言的运算符包含的范围很广泛,共有34种运算符。C语言把括号、赋值、强制类型转换等都作为运算符处理。从而使C语言的运算类型极其丰富,表达式类型多样化。灵活使用各种运算符可以实现在其它高级语言中难以实现的运算。   
(3)数据类型丰富。C语言的数据类型有:整型、实型、字符型、数组类型、指针类型、结构体类型、共用体类型等。能用来实现各种复杂的数据结构的运算。并引入了指针概念,使程序效率更高。另外C语言具有强大的图形功能,支持多种显示器和驱动器。且计算功能、逻辑判断功能强大。
(4)语法限制不太严格,程序设计自由度大。虽然C语言也是强类型语言,但它的语法比较灵活,允许程序编写者有较大的自由度。   
4.1 主程序模块程序设计
本系统的整个程序流程是首先上电,系统各部分进行初始化,单片机初始化,液晶显示器初始化等。初始化完成后进行键盘扫描,然后再进行延时一段时间,供传感器采集数据,延时完成后就进行数据的采集并传输到单片机,单片机处理之后传输到液晶显示器,液晶显示器显示温湿度值。并且判断温度和湿度是否超出阈值,如果没有超过,就继续执行数据采集程序,如果有一个值超出阈值,则启动报警系统,蜂鸣器发出声音,温湿度检测结束。主程序流程图如图4.1所示。


液晶显示模块是一个慢显示器件,在执行每条指令之前要确认模块的忙标志为低电平,表示不忙,则此指令失效,要显示字符时要先输入显示字符地址,告诉模块在哪里显示了字符。1602液晶显示模块可与单片机接口直接连接,无需再加驱动。
LCD1602的显示数据过程是首先液晶初始化,初始化完成后执行延时程序,等待数据的采集,延时完成后LCD会先写入一些指令和显示字符的地址,在这完成后单片机会向LCD发送数据即写数据,数据发送完LCD就会读取写入的地址并显示出来,最后返回。软件流程图如图4.2所示。





图4.3 DHT11传感器模块的软件流程图

传感器模块负责温湿度数据源的采集,首先数据口连接端P1.0输出低电平,延时18ms之后P1.0输出高电平,延时40ms之后,读P1.0引脚是否为低电平,如果不是低电平就继续读,如果是低电平就执行判断从机80μs高电平是否结束,如果没有结束就继续判断,如果结束就进行单片机数据接收,将接收到的数据按十进制数位存入指定的数组中,数据采集结束并保持数据采集持续进行。

4.4 键盘模块设计

键盘模块是用来设置系统阈值的,首先通过模式选择键开阈值并选择温度和湿度的设置,加一键和减一键是对温度和湿度的设置。第一次按模式键然后经过延时可以开阈值和进行湿度的设置,第二次按模式键并延时是温度的设置,第三次按模式键是关阈值。
键盘模块软件流程图如图4.4所示。







图4.4 键盘模块软件流程图

4.5 小结

本系统的软件设计采用了C语言编程,只需对温度和湿度进行相应的采集处理后,即可让液晶实时显示当前的温度与湿度值。报警模块只需接上单片机的I/O 口,并对其接口线进行编程方可,当温度与湿度超过阈值时报警模块就会报警。这样就可以完成环境中温湿度的检测。
    本设计在完成硬件电路设计并焊接好电路硬件的基础上,通过串口模块将软件代码下载至AT89C51单片机中完成系统集成。由于采用了AT89C51单片机,性能可靠、电路简单,系统中还可充分利用AT89C51中先进的软件硬件资源,便于软件系统的升级,操作方便。


设计制作51单片机DHT11的温湿度检测系统,程序设计及试工作是一项重要内容,所设计的程序51单片机DHT11的温湿度检测系统程序只是在编译环境下通过编译,消除编程工作中产生的语法错误后,直接将程序写入单片机中与硬件一起进行联调,如果这时硬件设计制作是正确的还好说,只需要进行软件的调试修改,烧写到硬件环境中验证直到达到设计要求即可,但这个工作也是需要反复不停地修改程序并烧录到硬件单片机中进行调试,但如果说硬设计、制作及程序设计都存在问题,整个调试工作就显得无从下手,给软件调试、硬件故障排出带来非常大的困难,增加不少工作量,甚至造成系统设计制作的失败。有好的解决办法吗?回答是肯定的,就是程序仿真,编译通过的程序,在Proteus环境下,按设计的硬件原理图,把仿真图画好,调入程序在Proteus仿真环境下进行程序的仿真,来验证程序设计的正确性及各项功能是否达到设计要求,在仿真环境下完成程序的调试工作。通过仿真调试满意后的程序,再烧写到硬件环境下调试,这时,如果硬件工作正常,可以进一步的验证程序的功能及正确性,如果工作不正常,这时可排出软件设计的问题,集中精力排出硬件设计、制作的问题,有针对性的排出,从而可提高设计制作过程中的效率,大大减轻制作工作量,使单片机DHT11的温湿度检测系统制作成功率可以得到100%的保证。下图是本设计的仿真图。

6  设计中遇到的问题及解决方法

6.1 硬件问题及解决方法

   (1)LCD1602不显示:
    检查LCD各个端口与单片机的连接是否接通,发现都通着,又检查了LCD数据口连接顺序与单片机的I/O口顺序是否一致,最后发现LCD的数据口顺序接反了,最后把LCD的D0-D7接单片机的I/O口P0.0-P0.7后,工作正常了。。
   (2)蜂鸣器不响:
因为刚开始不知道老师给的三极管是啥型号的,自己就用万用表测试了一下就焊接上了,结果不响,我就按照三极管的型号上网查了一下结果发现自己检测错了,自己的是PNP型的,三个管脚分别是字面对着自己ebc。然后卸下来重新焊上去蜂鸣器就响了。
   (3)LCD1602显示乱码:
把程序下载到单片机上,液晶显示的不是程序要显示的内容。我就用万用表检查8根数据线是否都接通,结果发现都是连通的。然后就考虑是不是数据线短路了,用万用表分别测量8跟数据线有没有短路的,结果发现有一根在焊接的时候不小心焊到旁边的焊盘上了,导致数据线接到了电源线上,那根数据线就会一直显示高电平,所以显示就乱码了。用烙铁把连接的焊锡分开以后,重新上电发现液晶显示正常了。

6.2 软件所遇问题及解决方法

   (1)键盘问题
按键没有按照程序设计的工作,模式键没有起作用,加减键也不规律的进行加减。通过仔细检查程序,通过检查按键硬件电路发现按键电路都好着呢,然后再检查程序,发现程序中按键按下之后没有用延时程序,就给程序中各个按键后边加了个延时程序,下载程序之后发现按键可以实现功能了。
   (2)湿度显示不稳定
在数据采集完成以后,显示在显示器上,发现湿度显示不稳定,一直在跳动。刚开始以为是正常情况,可是最后发现跳动的特别厉害,跳动幅度也很大。最后想到可能是单片机一直在采集数据然后显示数据,中间没有停歇才导致显示不稳定,就给数据采集前加了个延时程序,通过串口下载程序后,发现湿度显示稳定了。

随着社会的发展,科技越来越越发达,我们的生活也越来越智能化。温湿度是我们生活环境中的两个重要的参数,在我们的生活中,我们要时刻关心环境的变化,只有很好的把握好环境的差异变化,我们才能更好的生存与发展。
本文设计的温、湿度智能测控系统主要有以下几个各方面:
(1)采用AT89C51单片机为控制核心;
(2)采用数字式温度传感器DHT11为温、湿度数据采集器件,通过PC机作为人机接口,实现了数据采集与测控指令参数的设置;
(3)显示部分采用已标准的1602液晶为显示屏,具有显示质量高、体积小、功耗低等优点。
本系统整体设计具有界面友好、控制灵活、硬件系统集成度高、电路简单、功能强、性能可靠、成本低等特点。对我们的生活特别有帮助 。
在这次设计中我也学到了很多东西主要,原来在课堂上学习的单片机知识都是理论,从没有实践过,这次设计就让我的理论知识应用到了实践中。经过近这一段时间的努力,从拿到题目,到后来查找资料,理论学习,焊接电路板,实验编程调试,这一切都使我的理论知识和动手能力有了很大的提高。了解了单片机的硬件结构和软件编程方法,对单片机的工作方式有了很大的认知。同时,对一些外围设备比如传感器、液晶屏、键盘、蜂鸣器等有了一定的了解。
本系统具有较强的实用性,具体方面有:
(1)我对DHT11与DS18B20及一些水银温湿度测量器的测量数据进行了比较,验证了DHT11测量数据的准确性和稳定性。低廉的价格、小巧的体积、准确稳定的测量数据、简单的单总线控制方式、简洁的电路连接,这些将使DHT11拥有良好的应用前景;
(2)LCD1602液晶具有显示质量高、体积小、功耗低等优点,在以后会得到更广泛的应用。


附录1 硬件原理图




附录2 PCB图

附录3元件布置图
源程序
  1. #include <REGX51.H>
  2. #include <intrins.h>
  3. #include <math.h>     
  4. #include <stdio.h>      

  5. #define uchar unsigned char
  6. #define uint unsigned int
  7.                         //24c02读指令
  8. sbit DATA=P1^0;
  9. // AT24C02 数据端

  10. sbit k1=P3^4;                               //按键
  11. sbit k2=P3^5;                               //按键
  12. sbit k3=P3^6;                               //按键
  13. sbit k4=P3^7;                               //按键
  14. sbit beep=P2^3;
  15. sbit led1=P1^2;
  16. sbit led2=P1^3;
  17. sbit led3=P1^4;
  18. sbit led4=P1^5;
  19. sbit led5=P1^6;
  20. sbit led6=P1^7;

  21. sbit RS  = P2^0;
  22. sbit RW  = P2^1;
  23. sbit E  = P2^2;
  24. sfr DBPort  = 0x80;     //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口



  25. uchar temp,humi;
  26. uchar error;                                //用于检验是否出现错误
  27. uchar checksum,nn;                          //CRC                    
  28. uchar nn;                                         //蜂鸣器                    
  29. uchar TEMP_data[6];                         //用于记录实测的温度
  30. uchar HUMI_data[5];                         //用于记录实测的湿度
  31. uchar set_temp[5];                          //保存设定的温度
  32. uchar set_humi[4];                          //保存设定的湿度
  33. uchar idata temp_humi_cache[8];             //温湿度设置缓存
  34. uint temp_high;                                 //温度上限变量
  35. uint temp_low;                              //温度下限变量
  36. uint humi_high;                             //湿度上限变量
  37. uint humi_low;                              //湿度下限变量
  38. uchar presskeynum;                          //按键次数变量
  39. uchar  U8FLAG,k;
  40. uchar  U8count,U8temp;
  41. uchar  U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;
  42. uchar  U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;
  43. uchar  U8comdata;
  44. uchar  count, count_r=0;

  45. /********     1602函数声明     ********/
  46. void LCD_Initial();
  47. void GotoXY(unsigned char x, unsigned char y);
  48. void Print(unsigned char *str);
  49. void LCD_Write(bit style, unsigned char input);

  50. /*************************************************************************/


  51. void Delay1(uint );
  52. void  Delay_10us(void);
  53. void  COM(void);
  54. uchar RH(void);

  55. //1602程序
  56. //内部等待函数*************************************************************
  57. unsigned char LCD_Wait(void)
  58. {
  59.     RS=0;
  60.     RW=1;    _nop_();
  61.     E=1;    _nop_();           
  62.     E=0;
  63.     return DBPort;  
  64. }
  65. //向LCD写入命令或数据********************************************************
  66. #define LCD_COMMAND         0      // Command
  67. #define LCD_DATA            1      // Data
  68. #define LCD_CLEAR_SCREEN    0x01      // 清屏
  69. #define LCD_HOMING          0x02      // 光标返回原点
  70. void LCD_Write(bit style, unsigned char input)
  71. {
  72.     E=0;
  73.     RS=style;
  74.     RW=0;        _nop_();
  75.     DBPort=input;   _nop_();//注意顺序
  76.     E=1;        _nop_();//注意顺序
  77.     E=0;        _nop_();
  78.     LCD_Wait();
  79. }

  80. //设置显示模式************************************************************
  81. #define LCD_SHOW            0x04    //显示开
  82. #define LCD_HIDE            0x00    //显示关

  83. #define LCD_CURSOR          0x02    //显示光标
  84. #define LCD_NO_CURSOR       0x00    //无光标        

  85. #define LCD_FLASH           0x01    //光标闪动
  86. #define LCD_NO_FLASH        0x00    //光标不闪动

  87. void LCD_SetDisplay(unsigned char DisplayMode)
  88. {
  89.     LCD_Write(LCD_COMMAND, 0x08|DisplayMode);
  90. }

  91. //设置输入模式************************************************************
  92. #define LCD_AC_UP       0x02
  93. #define LCD_AC_DOWN         0x00      // default

  94. #define LCD_MOVE            0x01      // 画面可平移
  95. #define LCD_NO_MOVE         0x00      //default

  96. void LCD_SetInput(unsigned char InputMode)
  97. {
  98.     LCD_Write(LCD_COMMAND, 0x04|InputMode);
  99. }

  100. //初始化LCD************************************************************
  101. void LCD_Initial()
  102. {
  103.     E=0;
  104.     LCD_Write(LCD_COMMAND,0x38);           //8位数据端口,2行显示,5*7点阵
  105.     LCD_Write(LCD_COMMAND,0x38);
  106.     LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR);    //开启显示, 无光标
  107.     LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);   //清屏
  108.     LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE);       //AC递增, 画面不动
  109. }

  110. //液晶字符输入的位置************************
  111. void GotoXY(unsigned char x, unsigned char y)
  112. {
  113.     if(y==0)
  114.         LCD_Write(LCD_COMMAND,0x80|x);
  115.     if(y==1)
  116.         LCD_Write(LCD_COMMAND,0x80|(x-0x40));
  117. }

  118. //将字符输出到液晶显示
  119. void Print(unsigned char *str)
  120. {
  121.     while(*str!='\0')
  122.     {
  123.         LCD_Write(LCD_DATA,*str);
  124.         str++;
  125.     }
  126. }


  127. /****************************24C02程序部分******************************************

  128. /**********************************************************************************/

  129. void Delay24(void)
  130. {unsigned char i;
  131.    for(i=0;i<20;i++);

  132. }
  133. //***********************************************************************************
  134. void Delay24_10ms(void)
  135. {unsigned int i;
  136.    for(i=0;i<500;i++);
  137. }

  138. //****读一字节************************************

  139. void  Delay_10us(void)
  140. {
  141.     uchar i;
  142.     i--;
  143.     i--;
  144.     i--;
  145.     i--;
  146.     i--;
  147.     i--;
  148. }

  149. void  COM(void)
  150. {
  151.     uchar i;
  152.     for(i=0;i<8;i++)           
  153.     {
  154.               U8FLAG=2;
  155.                    while((!DATA)&&U8FLAG++);
  156.                 Delay_10us();
  157.                 Delay_10us();
  158.                 Delay_10us();
  159.                   U8temp=0;
  160.         if(DATA)U8temp=1;
  161.                 U8FLAG=2;
  162.                 while((DATA)&&U8FLAG++);                  
  163.                    if(U8FLAG==1)break;
  164.                     U8comdata<<=1;
  165.                    U8comdata|=U8temp;        
  166.     }
  167. }

  168. //--------------------------------
  169. //-----温湿度读取子程序 ------------
  170. //--------------------------------
  171. //----以下变量均为全局变量--------
  172. //----温度高8位== U8T_data_H------
  173. //----温度低8位== U8T_data_L------
  174. //----湿度高8位== U8RH_data_H-----
  175. //----湿度低8位== U8RH_data_L-----
  176. //----校验 8位 == U8checkdata-----
  177. //----调用相关子程序如下----------
  178. //---- Delay();, Delay_10us();,COM();
  179. //--------------------------------
  180. uchar RH(void)
  181. {
  182.     DATA=0;                                                  //主机拉低18ms
  183.         Delay1(180);                                  //原来为5
  184.         DATA=1;                                                //总线由上拉电阻拉高 主机延时20us
  185.         Delay_10us();
  186.         Delay_10us();
  187.         Delay_10us();
  188.         Delay_10us();
  189.         DATA=1;                                                   //主机设为输入 判断从机响应信号
  190.         if(!DATA)                 //判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行         
  191.         {
  192.             U8FLAG=2;

  193.             while((!DATA)&&U8FLAG++);        //判断从机是否发出 80us 的低电平响应信号是否结束         
  194.             U8FLAG=2;
  195.                   while((DATA)&&U8FLAG++);    //判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
  196.             COM();                                                //数据接收状态
  197.             U8RH_data_H_temp=U8comdata;
  198.             COM();
  199.             U8RH_data_L_temp=U8comdata;
  200.             COM();
  201.             U8T_data_H_temp=U8comdata;
  202.             COM();
  203.             U8T_data_L_temp=U8comdata;
  204.             COM();
  205.             U8checkdata_temp=U8comdata;
  206.             DATA=1;
  207.             U8temp=(U8T_data_H_temp+U8T_data_L_temp+U8RH_data_H_temp+U8RH_data_L_temp);        //数据校验
  208.             if(U8temp==U8checkdata_temp)
  209.             {
  210.                       U8RH_data_H=U8RH_data_H_temp;
  211.                       U8RH_data_L=U8RH_data_L_temp;
  212.                       U8T_data_H=U8T_data_H_temp;
  213.                       U8T_data_L=U8T_data_L_temp;
  214.                       U8checkdata=U8checkdata_temp;
  215.             }

  216.                 return 1;
  217.         }
  218.         else                                                                           //传感器不响应
  219.         {
  220.            return 0;
  221.         }
  222. }

  223. void delay(uint z)                          //延时函数z为毫秒数
  224. {
  225.    int a,b;
  226.    for(a=z;a>0;a--)
  227.    for(b=120;b>0;b--);
  228. }

  229. void key()
  230. {
  231.    uchar m;
  232.    if (k1==0)                               //调整按键检测
  233.    {
  234.       delay(10);
  235.       if (k1==0)
  236.       {
  237.          presskeynum++;
  238.          if(presskeynum==5)
  239.          presskeynum=0;
  240.          while(k1==0);
  241.          LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);   //清屏
  242.       }
  243.    }
  244.    if(presskeynum==1)//温度上限设置
  245.    {
  246.       if(k2==0)// 加
  247.       {
  248.          delay(300);
  249.          temp_high++;
  250.          if (temp_high>99)
  251.          temp_high=0;
  252.          if (temp_high<0)
  253.          temp_high=99;
  254.          while(k2==0);       //加上此句必须松按键才处理
  255.       }
  256.       if(k3==0)//减
  257.       {
  258.          delay(300);
  259.          temp_high--;
  260.          if (temp_high>99)
  261.          temp_high=0;
  262.          if (temp_high<0)
  263.          temp_high=99;
  264.          while(k3==0);       //加上此句必须松按键才处理
  265.       }
  266.    }
  267.    if(presskeynum==2)//温度下限设置
  268.    {
  269.       if(k2==0)// 加
  270.       {
  271.          delay(300);
  272.          temp_low++;
  273.          if (temp_low>99)
  274.          temp_low=0;
  275.          if (temp_low<0)
  276.          temp_low=99;
  277.          while(k2==0);
  278.       }
  279.       if(k3==0)
  280.       {
  281.          delay(300);
  282.          temp_low--;
  283.          if (temp_low>99)
  284.          temp_low=0;
  285.          if (temp_low<0)
  286.          temp_low=99;
  287.          while(k3==0);
  288.       }
  289.    }
  290.    if(presskeynum==3)//湿度上限设置
  291.    {
  292.       if(k2==0)// 加
  293.       {
  294.           delay(300);
  295.           humi_high++;
  296.           if (humi_high>99)
  297.           humi_high=0;
  298.           if (humi_high<0)
  299.           humi_high=99;
  300.           while(k2==0);
  301.       }
  302.       if(k3==0)
  303.       {
  304.           delay(300);
  305.           humi_high--;
  306.           if (humi_high>99)
  307.           humi_high=0;
  308.           if (humi_high<0)
  309.           humi_high=99;
  310.           while(k3==0);
  311.       }
  312.    }
  313.    if(presskeynum==4)//湿度下限设置
  314.    {
  315.       if(k2==0)//加
  316.       {
  317.           delay(300);
  318.           humi_low++;
  319.           if (humi_low>99)
  320.           humi_low=0;
  321.           if (humi_low<0)
  322.           humi_low=99;
  323.           while(k2==0);
  324.       }
  325.       if(k3==0)// 减
  326.       {
  327.           delay(300);
  328.           humi_low--;
  329.           if (humi_low>99)
  330.           humi_low=0;
  331.           if (humi_low<0)
  332.           humi_low=99;
  333.           while(k3==0);
  334.       }
  335.    }
  336.    if(k4==0)// 退出键
  337.    {
  338.       delay(10);
  339.       if(k4==0)
  340.       {
  341.           while(k4==0);
  342.           presskeynum=0;

  343.           LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);                           //清屏
  344.        }
  345.    }
  346. }
  347. void main()                                                         //主函数
  348. {
  349.    uchar t;
  350.    k1=k2=k3=k4=1;
  351.    for (t=0;t<=7;t++)

  352.    LCD_Initial();    //液晶初始化

  353.    while(1)
  354.    {
  355.        key();
  356.        if(presskeynum==0)
  357.        {  
  358.                         RH();                                               //测量温湿度
  359.                            temp=U8T_data_H;
  360.                            humi=U8RH_data_H;
  361.                    GotoXY(0,0);                                       //选择温度显示位置
  362.             Print("Temp:     C");                                             //5格空格
  363.             GotoXY(0,1);                                       //选择湿度显示位置
  364.             Print("Humi:     %");                                             //5格空格                           
  365.             GotoXY(5,0);                                       //设置温度显示位置
  366.                         if(temp>=10)
  367.                         {
  368.                     TEMP_data[0]=temp/10+'0';                                         //温度十位      
  369.                     TEMP_data[1]=temp%10+'0';                           //温度个位
  370.                         }
  371.                         else
  372.                         {
  373.                     TEMP_data[0]=' ';                                                         //温度十位      
  374.                     TEMP_data[1]=temp%10+'0';                           //温度个位
  375.                         }
  376.             TEMP_data[2]=0x2e;                                  //小数点
  377.             TEMP_data[3]='0';                               //温度小数点后第一位            
  378.             TEMP_data[4]=0xdf;                                  //显示温度符号℃
  379.             TEMP_data[5]='\0';
  380.             Print(TEMP_data);                                   //输出温度               
  381.             GotoXY(5,1);
  382.                         if(humi>=10)
  383.                         {
  384.                             HUMI_data[0]=humi/10+'0';                                         //湿度十位      
  385.                     HUMI_data[1]=humi%10+'0';                           //湿度个位
  386.                         }
  387.                         else
  388.                         {
  389.                             HUMI_data[0]=' ';                                                         //湿度十位      
  390.                     HUMI_data[1]=humi%10+'0';                           //湿度个位                        
  391.                         }                                                                   //设置湿度显示位置                                       
  392.             HUMI_data[2]='.' ;                                  //小数点
  393.             HUMI_data[3]='0';                               //湿度小数点后第一位   
  394.             HUMI_data[4]='\0';
  395.             Print(HUMI_data);                                   //输出湿度         
  396.             if ((temp)<temp_low)
  397.             {
  398.                                 led1=0;
  399.                                 led6=0;
  400.                         }
  401.                         else
  402.                         {
  403.                     led1=1;
  404.                                  led6=1;
  405.                         }
  406.             if ((temp+1)>temp_high)
  407.             led2=0;
  408.             else
  409.             led2=1;
  410.             if ((humi)<humi_low)
  411.             led3=0;
  412.             else
  413.             led3=1;
  414.             if ((humi+1)>humi_high)
  415.             led4=0;
  416.             else
  417.             led4=1;
  418.             if ((humi)<humi_low)                                                  //控制继电器加湿
  419.             led5=0;
  420.             else if ((humi)>=humi_high)  
  421.             led5=1;
  422.             if (((temp)<temp_low)|((temp+1)>temp_high)|((humi)<humi_low))
  423.             {
  424.                 for (nn=0;nn<50;nn++)
  425.                 {
  426.                     beep=0;
  427.                     delay(1);
  428.                     beep=1;
  429.                     delay(1);
  430.                 }
  431.             }
  432.             if ((humi)>humi_high)
  433.             {
  434.                 for (nn=0;nn<10;nn++)
  435.                 {
  436.                     beep=0;
  437.                     delay(1);
  438.                     beep=1;
  439.                     delay(1);
  440.                 }
  441.             }               
  442.         }
  443.         if(presskeynum==1)                                      //设定温度上限时显示的内容
  444.         {
  445.             set_temp[0]=temp_high/10+0x30;
  446.             set_temp[1]=temp_high%10+0x30;
  447.             set_temp[2]=0xdf;
  448.             set_temp[3]='C';
  449.             set_temp[4]='\0';
  450.             GotoXY (0,0);
  451.             Print("SET TEMP HIGH:");
  452.             GotoXY (0,1);
  453.             Print(set_temp);
  454.         }
  455.         if(presskeynum==2)                                      //设定温度下限时显示的内容
  456.         {
  457.             set_temp[0]=temp_low/10+0x30;
  458.             set_temp[1]=temp_low%10+0x30;
  459.             set_temp[2]=0xdf;
  460.             set_temp[3]='C';
  461.             set_temp[4]='\0';
  462.             GotoXY (0,0);
  463.             Print("SET TEMP LOW:");
  464.             GotoXY (0,1);
  465.             Print(set_temp);
  466.         }
  467.         if(presskeynum==3)                                      //设定湿度上限时显示的内容
  468.         {
  469.             set_humi[0]=humi_high/10+0x30;
  470.             set_humi[1]=humi_high%10+0x30;
  471.             set_humi[2]='%';
  472.             set_humi[3]='\0';
  473.             GotoXY (0,0);
  474.             Print("SET HUMI HIGH:");
  475.             GotoXY (0,1);
  476.             Print(set_humi);
  477.         }
  478.         if(presskeynum==4)                                      //设定湿度下限时显示的内容
  479.         {
  480.             set_humi[0]=humi_low/10+0x30;
  481.             set_humi[1]=humi_low%10+0x30;
  482.             set_humi[2]='%';
  483.             set_humi[3]='\0';
  484.             GotoXY (0,0);
  485.             Print("SET HUMI LOW:");
  486.             GotoXY (0,1);
  487.             Print(set_humi);
  488.         }      
  489.     }
  490. }

复制代码
以上的Word格式文档51黑下载地址:
源程序.docx (17.1 KB, 下载次数: 20)
SD002_基于DHT11的温湿度控制系统设计.doc (4.77 MB, 下载次数: 27)


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表