找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于单片机空气质量检测仪毕业设计论文下载 含源码 原理图等

  [复制链接]
跳转到指定楼层
楼主
完整的论文及源码下载(word格式可编辑):
基于单片机空气质量检测仪设计.doc (3.94 MB, 下载次数: 382)


下面是论文的部分内容预览:


图4-1 硬件实物图


基于单片机空气质量检测仪设计

摘  要

随着我国经济的发展,人民生活水平的提高,人们对环境问题及健康问题日益重视,室内空气品质(IAQ)状况受到越来越多的关注。人的一生中有三分之二的时间是在居室内度过的。本文研究的室内便携式智能空气品质监测仪是以室内空气中有毒有害气体的监测监控为背景,是以STC工公司的一款8位超低功耗单片机STC90C51为控制核心,能够实现对室内温度,湿度,VOC气体的实时采集处理、显示、报警等功能。仪器采用锂电池供电,具有良好的便携性和通用性,并且使用LCD1602点阵式液晶屏显示菜单,有良好的人机对话界面。同时设计了声光报警系统,实现在参数超标时及时的报警。室内智能空气品质监测仪体积小,功耗低,操作简单,适合应用于家庭和社区的医疗健康保健,能够实时知道室内空气的质量。


目  录

前  言
第1章              本课题的主要研究内容、方法及总体设计
§1.1 课题设计的内容
§1.2课题设计的方法
第2章 空气质量检测仪的硬件设计
§2.1 空气质量检测仪系统简介
§2.1.1 系统硬件结构及原理
§2.2 STC90C51单片机简介
§2.2.1STC90C51主要性能参数:
§2.2.2时钟电路模块
§2.2.3复位电路模块
§2.3传感器的选用
§2.3.1气体传感器
§2.3.2温湿度传感器
§2.4模数转换电路设计
§2.5声光报警电路设计
§2.6液晶显示电路设计
§2.6.1LCD1602的基本参数及引脚功能
§2.6.2LCD1602的指令说明及时序
§2.6.31602LCD的RAM地址映射及标准字库表
§2.6.4LCD1602的一般初始化过程
§2.7按键电路设计
§2.8电路电源设计
§2.9本章小结
第3章 空气质量检测仪的软件设计
§3.1 系统软件设计思路
§3.1.1 编程语言的选择
§3.1.2 软件功能需求
§3.2软件模块设计
§3.2.1主程序模块
§3.2.2AD转换模块
§3.2.3液晶显示模块
§3.2.4声光报警模块
§3.2.5按键模块
§3.3本章小结
第4章 仿真调试
§4.1系统硬件调试
§4.1.1 常见的硬件故障
§4.1.2硬件调试方法
§4.2 系统软件调试
§4.3本章小结
结  论            
§1主要结论
§2展望
参考文献
致 谢
附 录
附录一
附录二




河南科技大学毕业设计(论文)
前  言

一、课题研究的目的及意义
空气质量的好坏反映了空气污染程度,它是依据空气中污染物浓度的高低来判断的。来自固定和流动污染源的人为污染物排放大小是影响空气质量的最主要因素之一。空气质量检测种类包括装修污染、办公室内空气检测、作业场所有害物质检测、食堂油烟检测、锅炉大气及工业窑炉检测及工厂排放工业废气检测。
当今,人类正面临“煤烟污染”、“光化学烟雾污染”之后,又出现了“室内空气污染”为主的第三次环境污染。美国专家检测发现,在室内空气中存在500多种挥发性有机物,其中致癌物质就有20多种,致病病毒200多种。危害较大的主要有:氡、甲醛、苯、氨以及酯、三氯乙烯等。大量触目惊心的事实证实,室内空气污染已成为危害人类健康的“隐形杀手”,也成为全世界各国共同关注的问题。据统计,全球近一半的人处于室内空气污染中,室内环境污染已经引起35.7%的呼吸道疾病,22%的慢性肺病和15%的气管炎、支气管炎和肺癌。
本课题主要研究设计基于量化检测的“空气质量检测仪”系统,此系统旨在实现室内空气温度、湿度、有害气体的预警监测,有利于进行全方位的评价室内空气质量,为人类营造一个健康的室内生存空间。空气质量检测仪体积小,功耗低,操作简单,适合应用于家庭和社区的医疗健康保健,能够实时知道室内空气的质量。
二、国内外的研究状况
气体传感器测定甲醛成为近年来甲醛检测研究的新热点。早在1983年,压电类甲醛传感器就已问世。这种传感器可以不需要对样品进行任何处理就可以测定,但易受水分子的影响而使晶体震动频率发生漂移,故基本无实用性。为适应室内空气甲醛现场快速检测的要求,目前已开发出不少甲醛快速测定仪,这些仪器可直接在现场测定甲醛浓度,操作方便,适用于室内和公共场所空气中甲醛浓度的现场测定,也适用于环境测试舱法测定木质板材中的甲醛释放量。但这些仪器的工作原理、响应性能、适应范围等都不同。
在测试甲醛、苯等害气体方面,国外比较出名的有:美国ESC公司生产的Z一300甲醛检测仪、英国PPM公司生产的PPM-400甲醛检测仪;国内的有:江苏安普电子工程有限公司生产的400型甲醛分析仪、北京宾达绿创科技有限公司生产的甲醛测定仪抑一308等。
这些仪器可实现对有害气体的检测功能,适用于专业检测机构或实验研究机构。准确测定甲醛、苯、氨等有害气体的设备昂贵(如英国PPM公司生产的PPM400甲醛仪约两万多元),测定时间较长,每隔一段时间就需进行重新标定,需要专业人员进行操作,很难连续测定;目前国内外产品的设计差异主要集中在监测传感器和控制单片机芯片的选用,操作方面国外的产品操作界面方便,功能加完备。



  •          本课题的主要研究内容、方法及总体设计


§1.1 课题设计的内容

以单片机为核心,选择合适的传感器,实现对空气质量的检测。

§1.2课题设计的方法

查阅相关资料,应用电脑软件进行仿真、调试,制作硬件设备,在实际环境中测试并进行修改、调试,直至达到课题要求。

§1.3总体方案设计
本设计集VOC气体及温湿度监测,显示与报警于一体,利用MCU进行数据采集保证了前台数据的及时、准确,有利于进行全方位的评价。仪器采用锂电池供电,具有良好的便携性和通用性,并且使用LCD点阵式液晶屏显示菜单,有良好的人机对话界面。
§1.3.1系统框图


图1-1 系统总框图
§1.3.2功能设定
  • 显示部分采用LCD1602显示屏,循环显示各项测量的上下限及实际浓度、实际温度、湿度。并在按键选择情况下连续显示一个测量值的变化。
  • 当有害气体浓度超出安全范围时进行声光报警。
  • 按键操作可进行测量范围的调整,及手动和自动测量的转换。


第2章 空气质量检测仪的硬件设计


§2.1 空气质量检测仪系统简介

基于STC90C51的室内便携式智能空气质量监测仪是以室内空气中有毒有害气体的监测监控为背景,能够实现对室内温度,湿度,VOC气体的实时采集处理、显示、报警等功能。仪器采用锂电池供电,具有良好的便携性和通用性,并且使用LCD点阵式液晶屏显示菜单,有良好的人机对话界面。同时设计了声光报警系统,实现在参数超标时及时的报警。室内智能空气品质监测仪体积小,功耗低,操作简单,适合应用于家庭和社区的医疗健康保健,能够实时知道室内空气的质量。
§2.1.1 系统硬件结构及原理
本文研究的室内便携式智能空气品质监测仪是以STC工公司的一款8位超低功耗单片机STC90C51为控制核心。室内空气中有害气体通过传感器输出一个与气体浓度相对应的电压信号,该信号经过A/D转换电路按一定得采样频率将模拟信号转换为数字信号送入单片机进行数据采集以便进行显示处理,温湿传感器直接与单片机相连。单片机对采样值进行数字处理后驱动液晶显示器分别显示出被测室内空气中的VOC气体浓度值及温湿度。若被测室内空气中VOC气体的浓度有超过国家标准或设定的危险值或温湿度超出设定范围时报警电路对应的发出声光报警信号。

§2.2 STC90C51单片机简介

随着计算机技术的发展,单片机因具有集成度高、体积小、速度快、价格低等特点而在许多领域如过程控制、数据采集、机电一体化、智能化仪表、家用电器以及网络技术等方面得到广泛应用,从而使这些领域的技术水平、自动化程度大大提高。根据上述几方面及本课题的实际情况,单片机型号的选择主要从以下两点考虑:
一是要有较强的抗干扰能力。由于一般室内电子电器产品比较多,这对单片机的干扰较大,所以应采用抗干扰性能较好的单片机机型。
二是要有较高的性价比。由于高度的通用性和出色的稳定性,本系统采用宏晶公司产的低功耗,高性能CMOS 8位单片机的STC90C51作为控制器。片内含4k bytes的可系统编程的Flash只读程序存储器,器件采用ATMEL公司的高密度、非易失性存储技术生产,兼容标准8051指令系统及引脚。它集Flash程序存储器既可在线编程(ISP)也可用传统方法进行编程及通用8位微处理器于单片芯片中,可提供许多高性价比的应用场合,可灵活应用于各种控制领域。
§2.2.1STC90C51主要性能参数:







    • MCS.51产品指令系统完全兼容
    • 4k字节在系统编程(ISP)Flash闪速存储器
    • 1000次擦写周期
    • 4.0-5.5V的工作电压范围
    • 全境态工作模式:0Hz-33MHz
    • 三级程序加密锁
    • 128×8字节内部RAM
    • 32个可编程IO口线
    • 216位定时器计数器
10、6个中断源
11、全双工串行UART通道
12、低功耗空闲和掉电模式
13、中断可从空闲模唤醒系统
14、看门狗(wDT)及双数据指针
15、掉电标识和快速编程特性
16、灵活的在线系统编程
STC90C51芯片管脚如图2-1。
   
图2-1 STC90C51引脚布置
§2.2.2时钟电路模块
时钟电路由一个晶体振荡器12MHZ和两个30pF的瓷片电容组成。时钟电路用于产生单片机工作所需要的时钟信号,而时序所研究的是指令执行中各信号之间的相互关系。单片机本身就如一个复杂的同步时序电路,为了保证同步工作方式的实现,电路应在唯一的时钟信号控制下严格地工作。其电路如图2-2所示:
图2-2 时钟电路模块
§2.2.3复位电路模块
复位电路是使单片机的CPU或系统中的其他部件处于某一确定的初始状态,并从这状态开始工作,除了进入系统的正常初始化之外,当由于程序运行出错或操作错误使系统处于死锁状态时,为摆脱困境,也需按复位电路以重新启动。本设计采用的是按键复位电路。其电路如图2-3所示:
图2-3 复位电路模块

§2.3传感器的选用

§2.3.1气体传感器
1.气体传感器基础知识
按照气敏特性来分,气体传感器主要分为:半导体型、电化学型、固体电解质型、接触燃烧型、光化学型等气体传感器,又以前两种最为普遍。
    (1)半导体型气体传感器的优缺点
半导体气体传感器具有成本低廉、制造简单、灵敏度高、响应速度快、寿命长、对湿度敏感低和电路简单等优点。不足之处是必须在高温下工作、对气体或气味的选择性差、元件参数分散、稳定性不理想、功率高等方面。
(2)半导体传感器需要加热的原因
半导体传感器是利用一种金属氧化物薄膜制成的阻抗器件,其电阻随着气体含量不同而变化。气体分子在薄膜表面进行还原反应以引起传感器电导率的变化。为了消除气体分子达到初始状态就必须发生一次氧化反应。传感器内的加热器可以加速氧化过程,这也是为什么有些低端传感器总是不稳定,其原因就是没有加热或加热电压过低导致温度太低反应不充分。
(3)电化学气体传感器的工作原理
电化学气体传感器是通过监测电流来监测气体的浓度,分为不需供电的原电池式以及需要供电的可控电位电解式,目前可以监测许多有毒气体和氧气,后者还能监测血液中的氧浓度。电化学传感器的主要优点是气体的高灵敏度以及良好的选择性。不足之处是有寿命的限制一般为两年。
(4)半导体传感器和电化学传感器的区别
半导体传感器因其简单低价已经得到广泛应用,但是又因为它的选择性差和稳定性不理想目前还只是在民用级别使用。而电化学传感器因其良好的选择性和高灵敏度被广泛应用在几乎所有工业场合。
(5)固态电解质气体传感器
顾名思义,固态电解质就是以固体离子导电为电解质的化学电池。它介于半导体和电化学之间。选择性,灵敏度高于半导体而寿命又长于电化学,所以也得到了很多的应用,不足之处就是响应时间过长。
(6)接触燃烧式气体传感器
接触燃烧式气体传感器只能测量可燃气体。又分为直接接触燃烧式和催化接触燃烧式,原理是气敏材料在通电状态下,可燃气体在表面或者在催化剂作用下燃烧,由于燃烧使气敏材料温度升高从而电阻发生变化。后者因为催化剂的关系具有广普特性应用更广。
(7)光学式气体传感器
光学式气体传感器主要包括红外吸收型、光谱吸收型、荧光型等等,主要以红外吸收型为主。由于不同气体对红外波吸收程度不同,通过测量红外吸收波长来监测气体。目前因为它的结构关系一般造价颇高。基于本文的实时要求和性价比等方面的原因,本系统选用电化学传感器中的定电位电解式气体传感器。
本设计针对VOC气体选用能够侦测0.1ppm以上的气体的空气质量VOC气体浓度传感器MS1100用于检测空气中的甲醛、苯、二甲苯等检测空气中的甲醛、苯、二甲苯等多种有机挥发成分,具有极高的灵敏度和稳定性,体积小巧。实物如图2-4,使用时的连接电路如图2-5。
      
   图2-4 VOC传感器实物图      图2-5 VOC传感器接线图
§2.3.2温湿度传感器
温湿度传感器是指能将温度量和湿度量转换成容易被测量处理的电信号的设备或装置。温湿度传感器一般是测量温度量和相对湿度量。
鉴于测量温湿度的范围不大,精度要求不高故采用数字温湿度传感器DHT11。实物如图2-6。
图2-6 DHT11实物图
具有的特性:相对湿度和温度测量、全部校准,数字输出、卓越的长期稳定性、无需额外部件、超长的信号传输距离、超低能耗、4引脚安装、完全互换。
DHT11产品概述
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个DHT11传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式储存在OTP内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,信号传输距离可达20米以上,使其成为各类应用甚至最为苛刻的应用场合的最佳选则。产品为4针单排引脚封装。连接方便,特殊封装形式可根据用户需求而提供。
应用领域:
暖通空调、测试及检测设备、汽车、数据记录器、消费品、自动控制、气象站、家电、湿度调节器、医疗、除湿器。
传感器信息见表2-1。
表2-1 DHT11传感器信息
型号
测量范围
测湿精度
测温精度
分辨力
封装
DHT11
20-90%RH 0-50℃
±5%RH
±2℃
1
4针单排直插

  • 传感器性能说明见表2-2
表2-2 传感器性能说明
参数
条件
Min
Typ
Max
单位
湿度
分辨率


1
1
1
%RH


16


Bit
重复性




±1


%RH
精度
25℃


±4


%RH
0-50℃




±5
%RH
互换性
可完全互换
量程范围
0℃
30


90
%RH
25℃
20


90
%RH
50℃
20


80
%RH
响应时间
1/e(63%)25℃,1m/s空气
6
10
15
S
迟滞




±1


%RH
长期稳定性
典型值


±1


%RH/yr
温度
分辨率



1
1
1
16
16
16
Bit
重复性




±1


精度


±1


±2
量程范围


0


50
响应时间
1/e(63%)
6


30
S

2、 接口说明  
建议连接线长度短于20米时用5K上拉电阻,大于20米时根据实际情况使用合适的上拉电阻接线方式如图2-7。
图2-7 典型接线电路
3、电源引脚
DHT11的供电电压为              3-5.5V。传感器上电后,要等待 1s 以越过不稳定状态在此期间无需发送任何指令。电源引脚(VDD,GND)之间可增加一个100nF 的电容,用以去耦滤波。
4、串行接口  (单线双向)
DATA 用于微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数部分用于以后扩展,现读出为零.操作流程如下:
一次完整的数据传输为40bit,高位先出。
数据格式:8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和
数据传送正确时校验和数据等于“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”所得结果的末8位。
用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,用户可选择读取部分数据。从模式下,DHT11接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集,采集数据后转换到低速模式。
(1).通讯过程如图2-8所示
图2-8 通讯过程
操作时序如图2-9,总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us低电平响应信号。主机发送开始信号结束后,延时等待20-40us后,读取DHT11的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可,总线由上拉电阻拉高。
图2-9 操作时序
总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉高80us,准备发送数据,每一bit数据都以50us低电平时隙开始,高电平的长短定了数据位是0还是1。格式见下面图示,如果读取响应信号为高电平,则DHT11没有响应,请检查线路是否连接正常。当最后一bit数据传送完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态。            
数字0信号表示方法如图2-10所示
图2-10 数字0信号表示方法
数字1信号表示方法如图2-11所示
图2-11 数字1信号表示方法
5、测量分辨率
测量分辨率分别为 8bit(温度)、8bit(湿度)。
6、电气特性如表2-3
表2-3 电气特性
参数
条件
min
typ
max
单位
供电
DC
3
5
5.5
V

供电电流

测量
0.5


2.5
mA
平均
0.2


1
mA
待机
100


150
uA
采样周期
1





注:采样周期间隔不得低于1秒钟。
7、应用信息
7.1工作与贮存条件
超出建议的工作范围可能导致高达3%RH的临时性漂移信号。返回正常工作条后,传感器会缓慢地向校准状态恢复。要加速恢复进程/可参阅7.3小节的“恢复处理”。在非正常工作条件下长时间使用会加速产品的老化过程。
7.2暴露在化学物质中
电阻式湿度传感器的感应层会受到化学蒸汽的干扰,化学物质在感应层中的扩散可能导致测量值漂移和灵敏度下降。在一个纯净的环境中,污染物质会缓慢地释放出去。下文所述的恢复处理将加速实现这一过程。高浓度的化学污染会导致传感器感应层的彻底损坏。
7.3恢复处理
置于极限工作条件下或化学蒸汽中的传感器,通过如下处理程序,可使其恢复到校准时的状态。在50-60℃和< 10%RH的湿度条件下保持2小时(烘干);随后在20-30℃和>70%RH的湿度条件下保持5小时以上。
7.4温度影响
气体的相对湿度,在很大程度上依赖于温度。因此在测量湿度时,应尽可能保证湿度传感器在同一温度下工作。如果与释放热量的电子元件共用一个印刷线路板,在安装时应尽可能将DHT11远离电子元件,并安装在热源下方,同时保持外壳的良好通风。为降低热传导,DHT11与印刷电路板其它部分的铜镀层应尽可能最小,并在两者之间留出一道缝隙。
7.5光线
长时间暴露在太阳光下或强烈的紫外线辐射中,会使性能降低。
7.6配线注意事项
DATA信号线材质量会影响通讯距离和通讯质量,推荐使用高质量屏蔽线。
8、封装信息如图2-12,
图2-12 DHT11封装图
  • DHT11引脚说明见表2-4


表2-4 引脚说明
Pin
名称
注释
1
VDD
供电 3-5.5VDC
2
DATA
串行数据,单总线
3
NC
空脚,请悬空
4
GND
接地,电源负极

本设计采用的为DHT11模块,原理图为图2-13:
图2-13 DHT11模块接线图

§2.4模数转换电路设计

气体传感器出来的信号是模拟信号,而微处理器STC90C51只能处理数字信号,故需要对模拟信号信号进行转换,将其转换为处理器能识别的数字信号,由于测试电路出来的模拟电压变化范围在0~5V,故选择性价比比较合适的ADC0809进行模数转换。其管脚定义如图2-14所示。
图2-14 ADC0809管脚示意图
ADC0809各脚功能如表2-5:
表2-5 ADC0809各脚功能
引脚
功能介绍
D7-D0
IN0-IN7
8位数字量输出引脚
8位模拟量输入引脚
VCC
+5V工作电压
REF(+)
参考电压正端
REF(-)
参考电压负端
START
A/D转换启动信号输入端
ALE
地址锁存允许信号输入端
EOC
转换结束信号输出引脚,开始转换时为低电平,当转换结束时为高电平
OE
输出允许控制端,用以打开三态数据输出锁存器。
CLK
时钟信号输入端(一般为500KHz)。
A、B、C
地址输入线
ADC0809对输入模拟量要求:信号单极性,电压范围是0-5V,若信号太小,必须进行放大;输入的模拟量在转换过程中应该保持不变,如若模拟量变化太快,则需在输入前增加采样保持电路。ADC0809的时序接口为51系列单片机的标准总线接口,操作方便,如同对存储器或I/O操作一样,A/D转换精度为8比特,满足本课题要求。输入的模拟电压为0~5V,一次A/D转换时间为100μS。
ADC0809与单片机及VOC传感器的接线方式如图2-15:
图2-15 ADC0809接线原理图

§2.5声光报警电路设计

为了使本系统对室内空气品质的监测更为直观,采用了如图2-16由2个发光二极管和一个蜂鸣器构成的声光报警电路。其中VOC气体含量超标时双灯闪烁蜂鸣器报警,温度超标时D1灯亮蜂鸣器报警,湿度超标时D2灯亮蜂鸣器报警。
图2-16 声光报警电路

§2.6液晶显示电路设计

本课题所要显示的数据一共有6个,分别是有毒气体的浓度和室内的温度、湿度的范围和测量值,故选用2行16个字符的LCD1602作为显示模块,满足显示要求。液晶显示模块具有体积小、功耗低、显示内容丰富等特点,现在字符型液晶显示模块已经是单片机应用设计中最常用的信息显示器件了。
    字符型液晶显示模块是一种专门用于显示字母、数字、符号等点阵式LCD,目前常用16*1,16*2,20*2和40*2行等的模块。下面以长沙太阳人电子有限公司的1602字符型液晶显示器为例,介绍其用法。一般1602字符型液晶显示器实物如图2-17:
图2-17 1602字符型液晶显示器实物图
§2.6.1LCD1602的基本参数及引脚功能
1602LCD分为带背光和不带背光两种,基控制器大部分为HD44780,带背光的比不带背光的厚,是否带背光在应用中并无差别,两者尺寸差别如下图2-18所示:
图2-18 1602LCD尺寸图
1602LCD主要技术参数:
显示容量:16x2个字符芯片
工作电压:4.5V—5.5V
工作电流:2.0Ma(5V)
模块儿最佳工作电压:5.0V
字符尺寸:2.95×4.35(W×H)mm
引脚功能说明:
1602LCD采用标准的14脚(无背光)或16脚(有背光)接口,各引脚说明如表2-6所示:
表2-6  1602引脚说明
编号
符号
引脚说明
编号
符号
引脚说明
1
VSS
电源地
9
D2
数据
2
VDD
电源正极
10
D3
数据
3
VL
液晶显示偏压
11
D4
数据
4
RS
数据/命令选择
12
D5
数据
5
R/W
读/写选择
13
D6
数据
6
E
使能信号
14
D7
数据
7
D0
数据
15
BLA
背光源正极
8
D1
数据
16
BLK
背光源负极

第1脚:VSS为地电源。
第2脚:VDD接+5V正电源。
第3脚:VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。
第4脚:PS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
第5脚:R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或者显示地址,当RS为低电平R/W为高电平时可以读忙信号,当RS为高电平R/W为低电平时可以写入数据。
第6脚:E端为使能端,当E端由高电平跳变成低电平时,夜景模块执行命令。
第7~14脚:D0~D7为八位双向数据线。
第15脚:背光源正极。
第16脚:背光源负极。
§2.6.2LCD1602的指令说明及时序
1602液晶模块内部的控制器共有11条控制指令,如表2-7所示:


表2-7 控制命令表
序号
指令
RS
R/W
D7
D6
D5
D4
D3
D2
D1
D0
1
清显示
0
0
0
0
0
0
0
0
0
1
2
光标返回
0
0
0
0
0
0
0
0
1
*
3
置输入模式
0
0
0
0
0
0
0
1
I/D
S
4
显示开/关控制
0
0
0
0
0
0
1
D
C
B
5
光标或字符移位
0
0
0
0
0
1
S/C
R/L
*
*
6
置功能
0
0
0
0
1
DL
N
F
*
*
7
置字符发生存贮器地址
0
0
0
1
字符发生存贮器地址
8
置数据存贮器地址
0
0
1
显示数据存贮器地址
9
读忙标志或地址
0
1
BF
计数器地址
10
写数到CGRAM或DDRAM
1
0
要写的数据内容
11
从CGRAM或DDRAM读数
1
1
读出的数据内容

1602液晶模块的读写操作、屏幕和光标的操作都是通过指令编程来实现的。(说明: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:读数据。
与HD44780相兼容的芯片时序如表2-8:
表2-8 基本操作时序表
读状态
输入
RS=L,R/W=H,E=H
输出
D0—D7=状态字
写指令
输入
RS=L,R/W=L,D0—D7=指令码,E=高脉冲
输出
读数据
输入
RS=H,R/W=H,E=H
输出
D0—D7=数据
写数据
输入
RS=H,R/W=L,D0—D7=数据,E=高脉冲
输出

读写操作时序如图2-19和2-20所示:
图2-19 读操作时序
图2-20 写操作时序
§2.6.31602LCD的RAM地址映射及标准字库表
液晶显示模块是一个慢显示器件,所以在执行每条指令之前一定要确认模块的忙标志为低电平,表示不忙,否则此指令失效。要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,图2-21是1602的内部显示地址。
图2-21 1602LCD内部显示地址
第二行第一个字符的地址是40H,写入显示地址时要求最高位D7恒定为高电平1所以实际写入的数据应该是:
01000000B(40H)+10000000B(80H)=11000000B(C0H)。
在对液晶模块的初始化中要先设置其显示模式,在液晶模块显示字符时光标是自动右移的,无需人工干预。每次输入指令前都要判断液晶模块是否处于忙的状态。
1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码。
§2.6.4LCD1602的一般初始化过程
延时15mS
写指令38H(不检测忙信号)
延时5mS
写指令38H(不检测忙信号)
延时5mS
写指令38H(不检测忙信号)
以后每次写指令、读/写数据操作均需要检测忙信号
写指令38H:显示模式设置
写指令08H:显示关闭
写指令01H:显示清屏
写指令06H:显示光标移动设置
写指令0CH:显示开及光标设置
LCD1602的具体接线路图如图2-22所示。
图2-22 LCD1602接线电路图


§2.7按键电路设计

考虑到整个测量系统中不同环境对气体浓度及温湿度范围要求不同,故设置了按键功能,用于实现测量范围的调整,参考单片机引脚使用情况,共设置五个独立按键如图2-23,实现功能为设定键可进行设定的进入与退出,同时可实现三种范围的切换,另设左右移位键、上下调值键各两个,与此同时考虑到用户可能需要在一定时间内连续测量一种量,故设计了上调键的第二功能:当只有上调键按下时完成显示的自动与手动的切换以实现良好的人机对话。
图2-23 按键电路
§2.8电路电源设计

本设计采用集成稳压器7805,C29、C30分别为输入端和输出端滤波电容,D1为续流二极管。当输出电流较大时,7805应配上散热板。电源电路如图2-24所示:
图2-24 电源电路

§2.9本章小结

本章首先介绍了便携式室内空气质量监测仪的硬件结构以及系统功能,该仪器以8位单片机STC90C51作为控制核心,设计并构建了系统的硬件平台,完成了有毒气体浓度信号的采集转换电路、液晶显示电路、声光报警电路等的设计。该仪器能够实现有毒气体浓度信号和温湿度信号采集与显示及超标声光报警等功能。本章重点介绍了信号采集模拟电路和以主控制器为中心的数字电路的设计与工作原理。首先讨论了有毒气体采集模块中传感器选择问题,最后讨论了系统的外围接口电路模块,包括液晶显示,声光报警等,实现了各外围接口电路模块与STC90C51的硬件接口设计。
这一章比较具体的说明了系统硬件设计的内容,通过模块化的设计思想,把一个复杂的单片机系统按照功能划分成一个个单独的电路模型,分别进行设计,最后在集成到一起。这种方法对于设计复杂的单片机系统很有效。大大提高系统设计的效率与质量。(说明:系统硬件设计的电路原理图附在论文的附录里面。)


第3章 空气质量检测仪的软件设计


§3.1 系统软件设计思路

§3.1.1 编程语言的选择
在系统硬件电路确定以后,其主要功能的实现将依赖于软件来实现。对同一硬件电路,配以不同的软件,它所实现的功能也就不同,其设计软件基本要求:
1.可靠性。可靠性是软件设计的重要指标,具有较强的抗干扰能力。
2.易理解性、易维护性。编制的软件要求易阅读,容易发现和纠正错误,容易修改和补充。
3.实时性。系统能够及时响应外部事件的发生并能及时做出处理结果。
4.准确性。保证系统进行计算数据的精度。
目前存在有4种编程语言支持单片机,即汇编语言、PL/M51语言、C语言和BASI语言。其中汇编语言和C语言应用的较多,汇编语言的机器代码生成效率高,控制性好,但就是移植性不高。结合本系统的特点,这里选用了功能强、效率高的C语言。C语言主要有以下特点:用C语言编制的程序效率高,占用存储空间小,运行速度快。C语言能写出最优化程序,且能反映出计算机的实际运行情况。C语言能直接与存储器、接口电路打交道,也能申请中断。具有良好的模块化、容易阅读、维护等优点,且编写的模块程序易于移植。基于C语言和汇编语言的优缺点,本系统采用C语言编写方法。
§3.1.2 软件功能需求
室内空气质量检测仪系统软件主要由温湿传感器采集模块、AD转换模块、人机接口模块、声光报警模块、核心控制器模块构成,各模块功能概述如表3-1所示。


表3-1 各功能模块功能描述
功能模块
功能描述
温湿传感器采集模块
对室内温湿度测点进行实时监测
AD转换模块
1.完成信号采样
2.完成与核心处理器间的数据传输
核心控制器模块
1.系统时基分配
2.人机接口控制
3.各模块协调工作
人机接口模块
1.按键控制
2.动态信息显示
根据软件设计的基本要求,采取了如下的措施:
1.程序模块化。软件设计中包含有:主程序模块、显示模块、DHT11传感器检测函数、A/D数据转换子模块、声光报警模块、数据转换模块、按键函数。
2.软件设计采用C语言编程。
3.中断响应外部事件,提高了系统的实时处理事件能力。
4.软、硬件抗干扰。软件抗干扰措施提高了系统的可靠性。
以下就对一些主要模块进行详细的阐述。

§3.2软件模块设计

§3.2.1主程序模块
主程序运行流程图如图3-1所示。由主程序流程图可以看出,软件要实现的主要功能是实现对传感器信号的数据采集,然后进行数据的计算、分析、送液晶进行显示及报警功能。程序开始时,对系统进行初始化,包括单片机的各寄存器、RAM、定时器装载初值、中断设置及各模块初始化等。完成初始化后,CPU等待传感器传入信号及AD转换结束,从而完成当前监测参数的正确显示。





图3-1 主程序流程图
§3.2.2AD转换模块
AD完成转换需要一定的时间,AD应用中我们可以有两种方法来:
1.中断查询法,AD完成模数转换后会向中断输出端输出一个中断请求信号,告诉CPU转换已经完成,CPU可以读取数据。
2.延时等待法,设定一定的时间让CPU处于等待状态,此时间足够AD完成转换,过了等待时间CPU再去读取数据。
综合考虑各方面的因素,本研究采用第一种方法:延时等待法。所用的芯片为AD0809,根据所需的要求。
§3.2.3液晶显示模块
本设计所用的显示器件为1602液晶面板,该液晶能显示32个字符,满足显示要求。1602液晶与CPU是并口通信,由单片机的P2.5、P2.6、P2.7引脚来控制1602的读写数据命令功能,单片机P0口传输数据到1602进行显示。
系统上电LCD初始化,液晶显示首先需要要按照时序给定显示地址,然后传送数据。上电后液晶显示开始循环显示三个被测量的范围和测量结果。
§3.2.4声光报警模块
声音报警采用的是蜂鸣器,光报警是通过6个发光二极管来显示,3个绿色和三个红色的,当毒气含量没超标时显示绿色,超标时显示红色并启动蜂鸣器,报警子程序执行之前,设定的报警阈值存放在两个变量中,传感器输入AD转换值后,调用比较程序,小于阈值则执行显示程序,若大于阈值进行声光报警。。
§3.2.5按键模块
本设计设定按键功能为调整测量数据的安全范围并可进行手动和自动的切换考虑到实现按键功能所用按键数目不多及单片机引脚数量决定选用五个独立式按键,其中设定键用于进入和退出上下限的调整,上下左右四个键在设定键被按下的情况下可以对数值进行调整;同时,当设定键未按下且上调键被按下时进入上调键的第二功能,实现用户手动控制和自动控制的切换。已满足用户对环境条件检测要求的不同,实现良好的人机交流。

§3.3本章小结

在这一章里对室内便携式只能空气品质监测仪的软件设计进行了较详细的介绍。软件采用了模块化设计的思路,以单片机高级语言C51编程。在本章开始给出了主程序结构流程图,然后分别对各个子模块的软件流程进行介绍。(说明:程序见附录二)

1


河南科技大学毕业设计(论文)


第4章 仿真调试


§4.1系统硬件调试

§4.1.1 常见的硬件故障
(1)逻辑错误:硬件的逻辑错误是由于设计错误和加工过程中的工艺性错误所造成的,主要包括:错线、开路、短路等,其中短路最为常见,在印刷电路板布线密度高的情况下,极易因工艺原因造成短路。
(2)器件失效:元器件失效主要是因为器件本身已损坏或性能不符合要求,或者是由于组装错误造成的元器件失效,如电解电容、二极管的极性错误,集成块安装方向错误等。
(3)可靠性差:系统不可靠可能受多种因素影响,如金属化孔、接插件接触不良会造成系统时好时坏;内部和外部的干扰、器件负载过大等造成逻辑电平不稳定;另外,走线和布局的不合理等也是系统可靠性差的重要因素之一。
(4)电源故障:若系统中存在电源故障,则加电后将造成器件损坏。
§4.1.2硬件调试方法
拿到印刷电路板后,用万用表直接检查线路板各处是否有明显短路、断路的地方,尤其是电源是否短路。接着,焊接各元器件及插座,在焊接过程中要对各元件做逐一检查,比如二极管极性、电容容量及耐压、电阻值大小等。在插座、元件焊接完毕后,仔细检查元件面各元件之间裸露部分有无相互接触现象,焊接面的各焊点间、焊点和近邻线有无连接。最后,再给电路板空载上电(未插芯片),检查线路板各管脚及插件上的电位是否正确,特别是单片机管脚上的各点电压。若上述的一切都正常,则硬件调试的准备工作完成。
硬件实物如图4-1。

§4.2 系统软件调试

对系统软件编写完成之后,可以利用Keil C51仿真软件进行仿真运行调试,其调试界面如图4-2所示。
图4-2 KeilC51软件调试截面图
在具体的调试过程中,采取以下方法进行调试:在Keil C51编译环境中编写、编译软件模块,进行软件仿真调试,对功能模块的软件仿真。通过Keil C51的调试窗口观察各个寄存器、变量以及并行口输出的结果,监测软件模块运行的状态,在调试过程中不断地调整修改系统的软件程序,使系统实现预定功能。
调试过程中单步运行和断点运行调试只能验证程序正确与否,而不能确定定时精度、CPU的实时响应等问题,故在单步和断点调试之后,又进行了连续调试。待全部完成后,应反复运行调试多次,对系统的稳定性和操作是否符合原始设计要求、安排的操作是否合理等都要进行详细的观察,必要时作适当的修正。
调试完成后将程序导入protues中进行仿真,观察系统运行结果如图4-3。通过调试,确定基本可行后,将程序烧写单片机进行实物调整,通过不断烧写、试验,最终完成整个软件,准确实现要求的功能如图4-4。


图4-3 protues仿真调试


图4-4 实物调试

§4.3本章小结

本章首先详细描述用Keil C51对软件进行调试的过程以及其方法,通过输入不同的数据对系统进行调试,以确定本设计方案的正确性。本章工作内容使得硬件部分与软件部分结合实现预定的功能。

结  论


§1主要结论

    1.本系统综合利用传感器技术,自动监测技术,和微控制器技术,开发了一套对室内的空气质量进行监控的操作方便、简洁实用的自动监测系统。
2.系统软硬件设计合理,其中单片机软件采用模块化的程序设计方法,各模块相互独立,提高了系统的可靠性和可扩展性,整个系统具有较高的性能价格比。
3.系统C51语言编程,程序结构清晰,显示板界面非常友好,使得操作者在使用该系统时就像是在操作一台实际的控制仪器一样。
4.系统功能独立,配置合理。键盘设置为不同的用户提供了一定的选择空间。
5.经运行验证,系统具有响应速度快,操作简便,工作可靠等特点。

§2展望

1.本系统选用了集传感器,转换器于一体,能直接输出标准模拟信号的传感器,这无疑会增加系统的成本,今后可选用能达到要求的价格低廉的传感器,而信号的放大和调理电路部分可自行设计。
2.由于室内各种环境因子相互影响,而本系统的控制输出仅为简单的百分比信号量,这显然不能满足高精度的控制要求,应引入模糊算法,专家系统等技术以进一步提高系统的智能决策水平。
3.系统可以开发成多机监控模式,这就能同时监测多个环境室内的空气品质,通过串行通信传到上位机进行综合处理。
5.可通过网络与其他家电相联系,将把家庭中原来孤立、各不相关的设备统一起来。
6. 本设计可改为多路气体检测,未来可以实现更多的检测功能。
7. 本设计的主要强调智能化和人性化,例如可以适用于特殊人群——病人,他们可以把舒适的环境的指标通过相应的按键来控制,按下按键后,通过本系统控制相应的设备调节来达到是以病人的环境。
8.可以用来开发新型空调,现代空调都是针对空气温湿进行调节,可以将本设计加入空调内部,使其既能控制温湿度,还可以对空气中的各种气体进行检测,并通过控制“新风系统”改善空气各方面的质量。


参考文献

[1] 余永权.单片机原理及应用[M].北京:电子工业出版社,1998.12
[2] 余锡存、曹国华.单片机原理及接口技术[M].第二版.西安:西安电子科技大学出版社,2007.12
[3] 诸邦田.电子电路实用抗干扰技术[M].北京:人民邮电出版社,1994.5
[4] 曲喜新.电子元件材料手册[M].北京:电子工业出版社,1989.4
[5] 汪吉鹏、马云峰.微机原理与接口技术[M].北京:高等教育出版社,2001.7
[6] 田崴.电工技术(电工学1)[M].北京:高等教育出版社,2010.12
[7] 孙立功.电子技术(电工学2)[M].北京:高等教育出版社,2010.12
[8] 马玉春.串行通信协议的研究及应用[J].计算机应用研究.2004
[9] 胡汉才.单片机原理及其接口技术[M].清华大学出版社,1996.
[10] 楼然苗,李光飞.51系列单片机设计实例[M].北京航空航天大学出版社,2003.
[11] 赵亮,侯国锐.单片机C语言编程与实例[M].人民邮电出版社,2003.
[12] 张毅刚.单片机原理及应用[M].北京:高等教育出版社,2003.
[13] 何立民.单片机与嵌入式系统应用[M].北京航空航天出版社,2003.
[14]谭浩强.C程序设计(第三版)[M].清华大学出版社,2005.
[15]清源科技.Protel 99 SE电路原理图与PCB设计及仿真[M].机械工业出版社,2007.


致 谢

为期两个多月的毕业设计终于完成了,对我个人而言,凝聚了许多努力和汗水,也经受住了严峻的考验。和普通的课程设计不同,由于毕业设计的综合性,几乎用到所学的全部知识,而且是我第一次接触传感器的使用,对我来说这是一个全新的任务。由于基础过于薄弱,专业知识有限,浮躁的心理让我一开始举步维艰,满脑子想的就是放弃。在心理最为脆弱的时候,黄老师耐心地开导我,给我鼓励和信心,毕业设计才得以步入正轨。
    万事开头难,从研究课题,搜集材料,到正式投入设计,我花费了很多时间和精力。对于这次全新的设计,老师给了我很大的自由空间,可以充分发挥自己的创造思维。但是,对于很多新的尝试,我还是有所拘束。可能是性格使然吧,每当遇到问题,设计处于混沌状态时,烦躁焦虑接踵而来,让我迷失了方向。又是黄老师在最繁忙的时候,给我做细致的分析指导,让我茅塞顿开,使设计得以延续直至顺利完成。所以,在这次毕业设计中,我最感谢的是黄晓东老师,他给我们提供一流的设计场所,还提供了许多实用的设计资料,为我们的设计提供了保障。
在我看来,黄老师不仅是一位态度严谨,学识渊博的优秀教师,也是一位心理调节师,他总是能在设计氛围紧张的时候,给同学们带来欢乐,缓解同学们的压力。他那自信乐观的生活态度,也值得我们学习。从黄老师那里,我不仅学到了许多专业知识和实践经验,而且懂得许多做人的道理和生活的真谛,这些都是一辈子受用的财富,让我受益匪浅,终生难忘。
最后,再次对黄老师表示真诚的谢意和崇高的敬意。同时也对同组同学的帮助表示衷心的感谢。

附 录

附录一
硬件电气原理图


  1. #include<reg52.h>
  2. #include<intrins.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. #define Data  P0    //数据端口
  6. /*****1602管脚定义*****/
  7. sbit RS=P2^6;
  8. sbit RW=P2^5;
  9. sbit E=P2^7;
  10. /******AD管脚定义*****/
  11. sbit STA=P3^0;
  12. sbit OE=P3^1;
  13. sbit EOC=P3^2;
  14. sbit CLK=P3^3;
  15. /*****按键管脚定义******/
  16. sbit key_U=P2^0;
  17. sbit key_D=P2^1;
  18. sbit key_L=P2^2;
  19. sbit key_R=P2^3;
  20. sbit key_S=P2^4;
  21. /******报警用管脚******/
  22. sbit beep=P3^4;
  23. sbit led1=P3^5;
  24. sbit led2=P3^6;
  25. unsigned char num=0;//记录设定键按下次数
  26. unsigned char k_flag=0;//记录设置键按下次数(用于调用)
  27. unsigned char wei=0;//光标位置
  28. unsigned char c_num=0;//记录切换键按下次数
  29. unsigned char c_flag=0;//记录切换键按下次数(用于调用)
  30. unsigned char voc_ad;//AD读取数据
  31. unsigned char flag;//DHT11函数用到
  32. /****************************/
  33. sbit DHT=P3^7;
  34. uchar  WEN1[]="wen:16.00-28.00";              //温度第一行数据
  35. uchar  WEN2[]="      20.00    ";   //温度第二行数据
  36. uchar  SHI1[]="shi:30.00-70.00";              //湿度第一行数据
  37. uchar  SHI2[]="      20.00    ";   //湿度第二行数据
  38. uchar  VOC1[]="voc:0.00-2.70  ";              //湿度第一行数据
  39. uchar  VOC2[]="      0.00    ";   //湿度第二行数据
  40. unsigned char shiZ,shiX,wenZ,wenX,check;
  41. unsigned char tr_shiZ,tr_shiX,tr_wenZ,tr_wenX;
  42. /*********延时*******************************/
  43. void delay_1ms(uint x)
  44.   {
  45.     uchar i;
  46.     while(x--)
  47.     for(i=0;i<120;i++);
  48.   }
  49. void delay_10us()
  50.   {
  51.                             unsigned char i;
  52.                             i--;
  53.                             i--;
  54.                             i--;
  55.                             i--;
  56.                             i--;
  57.                             i--;
  58.   }
  59. void DelayUs(unsigned char us)                            //--延时函数
  60.   {
  61.                             unsigned char uscnt;
  62.                             uscnt=us>>1;        /*12MHz频率*/
  63.                             while(--uscnt);
  64.   }
  65. /*******1602显示*******************************************/
  66. /**********写命令**********/
  67. void lcd_write_com(uchar c)               
  68.   {
  69.     delay_1ms(5);//操作前短暂延时,保证信号稳定
  70.     E=0;
  71.     RS=0;
  72.     RW=0;
  73.     _nop_();
  74.     E=1;
  75.     Data=c;
  76.     E=0;
  77.   }
  78. /**********写数据*************/
  79. void lcd_write_dat(uchar c)                           
  80.   {
  81.     delay_1ms(5);  //操作前短暂延时,保证信号稳定
  82.     E=0;
  83.     RS=1;
  84.     RW=0;
  85.     _nop_();
  86.     E=1;
  87.     Data=c;
  88.     E=0;
  89.     RS=0;
  90.   }
  91. /**********LCD初始化********/
  92. void lcd_init()               
  93.   {
  94.     delay_1ms(15);
  95.     lcd_write_com(0x38); //display mode
  96.     lcd_write_com(0x38); //display mode
  97.     lcd_write_com(0x38); //display mode
  98.     lcd_write_com(0x06); //显示光标移动位置
  99.     lcd_write_com(0x0c); //显示开及光标设置
  100.     lcd_write_com(0x01); //显示清屏
  101.   }
  102. /*********显示单个字符**********/
  103. void ShowChar(uchar pos,uchar c)
  104.   {
  105.     unsigned char p;
  106.      if (pos>=0x10)
  107.        p=pos+0xb0; //是第二行则命令代码高4位为0xc
  108.      else
  109.        p=pos+0x80; //是第二行则命令代码高4位为0x8
  110.     lcd_write_com(p);//写命令
  111.     lcd_write_dat(c);   //写数据
  112.   }
  113. /*********显示字符串**********/
  114. void ShowString (uchar line,char *ptr)               
  115.   {
  116.     unsigned char l,*p;
  117.     p=ptr;
  118.     l=line<<4;
  119.      while((*p)!='\0')
  120.        {
  121.           ShowChar(l++,*(p));
  122.                                                               p++;
  123.         }
  124.   }
  125. /*********温度显示函数***********/
  126. void WENdisp(void)               
  127.   {
  128.                             ShowString(0,WEN1);
  129.                             _nop_();  
  130.                             ShowString(1,WEN2);
  131.   }
  132. /*********湿度显示函数***********/
  133. void SHIdisp(void)               
  134.   {
  135.     ShowString(0,SHI1);
  136.     _nop_();
  137.     ShowString(1,SHI2);
  138.   }
  139. /*********VOC调用的显示函数***********/
  140. void VOCdisp(void)               
  141.   {
  142.     ShowString(0,VOC1);
  143.     _nop_();
  144.     ShowString(1,VOC2);
  145.   }
  146. /***********报警用函数************/
  147. void Beep(unsigned char i,j)//i用于确定亮灯方式,j用于确定蜂鸣器是否报警
  148.   {
  149.     unsigned char m;
  150.     led1=led2=1;
  151.     for(m=0; m<250; m++)
  152.                                 {
  153.                                switch(i)
  154.                                               {
  155.                                                         case 0:break;
  156.                                                         case 1:led1=led2=0;break;//低电平点亮
  157.                                                         case 2:led1=0;break;
  158.                                                         case 3:led2=0;break;
  159.                        }
  160.         beep = j;
  161.         delay_1ms(2);
  162.                                           led1=led2=1;
  163.         beep = 0;
  164.         delay_1ms(2);
  165.                                 }
  166.   }
  167. void voc_warning()
  168.   {
  169.                               unsigned char voc_t;            
  170.                               unsigned char voc_h;
  171.       voc_t=('0'+VOC2[6])*10+('0'+VOC2[8]);
  172.       voc_h=('0'+VOC1[9])*10+('0'+VOC1[11]);
  173.                             if(voc_t>voc_h)
  174.                                           {
  175.                                             Beep(1,1);
  176.         }
  177.                   else Beep(0,0);
  178.   }
  179. void wen_warning()
  180.   {
  181.                 unsigned char wen_t;            
  182.                 unsigned char wen_h;
  183.                 unsigned char wen_l;
  184.       wen_t=('0'+WEN2[6])*10+('0'+WEN2[7]);
  185.       wen_l=('0'+WEN1[4])*10+('0'+WEN1[5]);
  186.       wen_h=('0'+WEN1[10])*10+('0'+WEN1[11]);
  187.                             if(wen_t>wen_h||wen_t<wen_l)
  188.                                           {
  189.                                               Beep(2,1);
  190.         }
  191.                             else Beep(0,0);
  192.   }
  193. void shi_warning()
  194.   {
  195.                               unsigned char shi_t;            
  196.                               unsigned char shi_h;
  197.                               unsigned char shi_l;
  198.       shi_t=('0'+SHI2[6])*10+('0'+SHI2[7]);
  199.       shi_l=('0'+SHI1[4])*10+('0'+SHI1[5]);
  200.       shi_h=('0'+SHI1[10])*10+('0'+SHI1[11]);
  201.                             if(shi_t>shi_h||shi_t<shi_l)
  202.                                           {
  203.                                              Beep(3,1);
  204.                                           }
  205.                   else Beep(0,0);
  206.   }
  207. /*******************按键***************************/
  208. /*************进入设定功能***************/
  209. unsigned char key_set(void)
  210.   {
  211.      if(key_S==0)
  212.        {
  213.                                                           delay_1ms(10);
  214.                                                           if(key_S==0)
  215.             {
  216.                                                  while(!key_S);
  217.               num++;
  218.                                                               k_flag=num%4;
  219.                                                   }
  220.                                                            else k_flag=num%4;
  221.         }
  222.       else k_flag=num%4;
  223.    return k_flag;            
  224.   }
  225. /********************调整数据******************/
  226. unsigned char key_adddec(unsigned char dat)
  227.   {
  228.    if(key_U==0)
  229.      {
  230.                                 delay_1ms(10);
  231.                                              if(key_U==0)
  232.           {
  233.                                                              while(!key_U);
  234.                                                                       if(dat<'9')
  235.                   dat++;
  236.                            else
  237.                               dat='9';
  238.                                                }
  239.       }
  240.     if(key_D==0)
  241.       {
  242.                                                         delay_1ms(10);
  243.                                               if(key_D==0)
  244.                          {
  245.                                                                            while(!key_D);
  246.                                                                if(dat>'0')
  247.                                                         dat--;
  248.                                          else
  249.                                             dat='0';
  250.                          }
  251.                                           }
  252.    return dat;            
  253.   }
  254. /***************左右移位*******************/
  255. unsigned char key_LR()
  256.   {
  257.                  if(key_L==0)
  258.       {
  259.                                           delay_1ms(10);
  260.                                           if(key_L==0)
  261.            {
  262.                                                             while(!key_L);
  263.                                                              if(wei==0)
  264.                                         wei=3;
  265.                                                             else wei--;
  266.             }
  267.        }
  268.     if(key_R==0)
  269.       {
  270.                                           delay_1ms(10);
  271.                                           if(key_R==0)
  272.           {
  273.             while(!key_R);
  274.                                               if(wei==3)
  275.                 wei=0;
  276.                                               else wei++;
  277.            }
  278.        }
  279.     return wei;
  280.   }
  281. /*********主函数调用的按键函数*********/
  282. void set_updn_dat(void)
  283.   {
  284.                             while(key_set())
  285.        {
  286.         unsigned j=key_LR();      
  287.             if(key_set()==1)
  288.               {
  289.                                                                          switch(j>0)
  290.                                                                                                      {
  291.                                                                                                                    case 1:j=2;break;
  292.                                                                                                                    case 0:j=0;break;
  293.                                                                                                   }
  294.                             VOCdisp();
  295.                                                                   VOC1[j+9]=key_adddec(VOC1[j+9]);
  296.                                                      lcd_write_com(0x80+j+9);
  297.                                                                   lcd_write_dat(VOC1[j+9]);        
  298.                           }
  299.                         else                       
  300.               if(key_set()==2)
  301.                 {
  302.                                                                                       switch(j)
  303.                                                                                                   {
  304.                                                                                                                    case 2:j=6;break;
  305.                                                                                                                    case 3:j=7;break;
  306.                                                                                                   }
  307.                                WENdisp();
  308.                                                      WEN1[j+4]=key_adddec(WEN1[j+4]);
  309.                                                      lcd_write_com(0x80+j+4);
  310.                                                                   lcd_write_dat(WEN1[j+4]);
  311.                                                  }
  312.             else                       
  313.               if(key_set()==3)
  314.                 {
  315.                                                                                       switch(j)
  316.                                                                                                   {
  317.                                                                                                                    case 2:j=6;break;
  318.                                                                                                                    case 3:j=7;break;
  319.                                                                                                   }
  320.                   SHIdisp();
  321.                                           SHI1[j+4]=key_adddec(SHI1[j+4]);
  322.                                                      lcd_write_com(0x80+j+4);
  323.                                                                   lcd_write_dat(SHI1[j+4]);
  324.                                                  }            
  325.                               }                           
  326.   }
  327. /*************手动自动切换功能**************/
  328. unsigned char key_change(void)
  329.   {
  330.      if(key_U==0)
  331.        {
  332.                                                             delay_1ms(10);
  333.                                                if(key_U==0)
  334.                                      {
  335.                                                                   while(!key_U);
  336.                                c_num++;
  337.                                                      c_flag=c_num%4;
  338.                                                   }
  339.                                                         else c_flag=c_num%4;
  340.         }
  341.      else c_flag=c_num%4;
  342.    return c_flag;            
  343.   }
  344. /*************************传感器函数************************/
  345. /**************DHT测试**************/
  346. /******温湿度读取函数*******/
  347. char DHTread_data()
  348.   {
  349.                             unsigned char i,num,temp;
  350.                             num=0;
  351.                             for(i=0;i<8;i++)
  352.                                             {
  353.                                                         flag=2;
  354.                                                         while((!DHT)&&flag++);
  355.                                                         delay_10us();
  356.                                                         delay_10us();
  357.                                                         delay_10us();
  358.                                                         if(DHT==1)
  359.                                                                         {
  360.                                                                                     temp=1;
  361.                                                                                     flag=2;
  362.                                                                                     while(DHT&&flag++);                                                      
  363.                                                                         }
  364.                                                         else
  365.                                                                       temp=0;
  366.                                                                       num<<=1;
  367.                                                                       num|=temp;
  368.                                             }
  369.                             return(num);
  370.   }
  371. /********初始化及采集程序*********/
  372. void DHTread_init()
  373.   {
  374.     DHT=0;                              //主机使DHT11低电平并延时至少18ms
  375.     delay_1ms(21);
  376.     DHT=1;                              //主机置DHT11高电平20~40us,并等待从机相应
  377.     delay_10us();
  378.     delay_10us();
  379.     delay_10us();
  380.     DHT=1;
  381.     if(!DHT)  //从机发出相应信号
  382.       {
  383.                                                         flag=2;
  384.                                                         while((!DHT)&&flag++);
  385.                                                         flag=2;
  386.                                                         while(DHT&&flag++);              //开始采集数据
  387.                                                         tr_shiZ=DHTread_data();//采集湿度整数部分
  388.                                                         tr_shiX=DHTread_data();//采集湿度小数部分
  389.                                                         tr_wenZ=DHTread_data();//采集温度整数部分
  390.                                                         tr_wenX=DHTread_data();//采集温度小数部分
  391.                                                         check=DHTread_data();              //采集校验位
  392.                                                         DHT=1;
  393.       }                                                         
  394.   }
  395. /*********显示测试结果*********/
  396. void DHT11()
  397.   {
  398.                  unsigned char temp;
  399.                   {
  400.                                    DHTread_init();
  401.                                   temp=tr_shiZ+tr_shiX+tr_wenZ+tr_wenX;
  402.                                               if(check==temp)
  403.                                                  {
  404.                                                                  shiZ=tr_shiZ;
  405.                                          shiX=tr_shiX;
  406.                                          wenZ=tr_wenZ;
  407.                                          wenX=tr_wenX;
  408.                          }
  409.            WEN2[6]='0'+wenZ/10;
  410.            WEN2[7]='0'+wenZ%10;            
  411.            WEN2[9]='0'+wenX/10;
  412.            WEN2[10]='0'+wenX%10;
  413.            SHI2[6]='0'+shiZ/10;
  414.            SHI2[7]='0'+shiZ%10;
  415.            SHI2[9]='0'+shiX/10;
  416.            SHI2[10]='0'+shiX%10;
  417.                   }
  418.   }
  419. /****************气体浓度检测************/
  420. /*********系统初始化***********/
  421. void init()
  422.   {
  423.                             TMOD = 0x01; //设定定时器T0工作方式
  424.                             TH0=(65536-2)%256;
  425.                             TL0=(65536-2)/256;
  426.                             ET0=1;  //允许T0中断
  427.                             EA=1; //开总中断
  428.                             TR0=1; //启动定时器T0
  429.   }
  430. /**********T0中断服务程序***********/
  431. void t0(void) interrupt 1 //using 1
  432.   {
  433.                             TH0=(65536-2)%256;
  434.                             TL0=(65536-2)/256;
  435.                             CLK=~CLK;
  436.   }  
  437. /**********AD转换函数**********/
  438. void AD()
  439.   {
  440.                             STA=0;
  441.     OE=0;
  442.                             STA=1; //启动AD转换
  443.                             _nop_();
  444.                             STA=0;
  445.     while(EOC==1);
  446.     OE=1;
  447.     voc_ad=P1;
  448.   }
  449. /*******数据处理********/
  450. void VOC()
  451.   {
  452.                             AD();
  453.                             VOC2[6]='0'+voc_ad/51;
  454.                             VOC2[8]='0'+voc_ad%51*10/51;
  455.                             VOC2[9]='0'+voc_ad%51*10%51*10/51;
  456.   }
  457. /************切换程序*************/
  458. void change(void)
  459.   {
  460.     while(!key_set() && key_change())
  461.        {
  462.                                                           unsigned k=key_change();
  463.             switch(k)
  464.                {
  465.                  case 1:
  466.                                                      VOC();
  467.                                                      VOCdisp();
  468.                                                                                                   voc_warning();
  469.                                                                                                   break;
  470.                  case 2:
  471.                                                      DHT11();
  472.                                                      WENdisp();
  473.                                                                                                   wen_warning();
  474.                                                                                                   break;
  475.                  case 3:
  476.                                                      DHT11();
  477.                                                      SHIdisp();
  478.                                                                                                   shi_warning();
  479.                                                                                                   break;
  480.                  }
  481.                                           }        
  482.   }
  483. /**********************主函数**************************/
  484. void main()
  485.   {
  486.                             lcd_init();
  487.     delay_1ms(50);
  488.                             init();
  489.     num=0;
  490.                             while(1)

  491. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏14 分享淘帖 顶2 踩
回复

使用道具 举报

沙发
ID:1 发表于 2017-6-3 03:58 | 只看该作者
好资料,51黑有你更精彩!!!
回复

使用道具 举报

板凳
ID:264022 发表于 2017-12-19 23:12 | 只看该作者
帖主,能把资料发给我吗
回复

使用道具 举报

地板
ID:518760 发表于 2019-4-22 16:58 | 只看该作者
我也想要附件
回复

使用道具 举报

5#
ID:729397 发表于 2020-4-15 00:44 | 只看该作者
帖主附件有吗
回复

使用道具 举报

6#
ID:484435 发表于 2020-6-6 20:00 | 只看该作者
谢谢分享
回复

使用道具 举报

7#
ID:484435 发表于 2020-6-9 09:52 | 只看该作者
谢谢分享
回复

使用道具 举报

8#
ID:484435 发表于 2020-6-9 09:55 | 只看该作者
谢谢大佬
回复

使用道具 举报

9#
ID:936286 发表于 2021-6-16 10:54 | 只看该作者
大佬有完整附件吗?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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