室内温湿度计
本项目通过单片机AT89S52控制数字温度传感器DS18B20和电容式相对湿度传感器HS1101,实现对室内温度和相对湿度的测量,并且在液晶显示器LCD1602上实时显示室内环境的温度和相对湿度。
1 项目功能说明
系统具体功能需求如下所述:
· 实现对室内温度的测量,分辨率为0.5℃
· 实现对室内相对湿度的测量,误差不大于±3%RH
· 实现室内温度和相对湿度的本地显示
2 系统整体
室内温湿度计的整体设计方案包括硬件设计方案和软件设计方案。硬件以微控制器为核心,外接晶振、复位电路、电源、温度测量电路、湿度测量电路、LCD显示电路组成。硬件设计方案如图1所示。
图1 系统硬件框图
系统软件整体设计
如图2所示。
图2 系统软件流程图
3 系统硬件设计
3.1 微控制器模块
鉴于系统对速度和成本的要求,本系统采用51系列单片机,具体选择美国ATMEL公司生产的AT89S52为控制器。
AT89S52是美国ATMEL公司生产的低功耗,高性能CMOS8位单片机,片内含8k bytes的可系统编程的Flash只读程序存储器,器件采用ATMEL公司的高密度、非易失性存储技术生产,兼容
8051指令系统及引脚。它集Flash程序存储器既可在线编程(ISP)也可用传统方法进行编程及通用8位微处理器于单片芯片中,ATMEL公司的功能强大,低价位AT89S52单片机可提供许多高性价比的应用场合,可灵活应用于各种控制领域。
AT89S52具有以下特点:
·与MCS-51产品指令系统完全兼容
·8k字节在系统编程(ISP)Flash闪速存储器
·1000次擦写周期
·4.0-5.5V的工作电压范围
·全静态工作模式:0Hz-33MHz
·三级程序加密锁
·256×8字节内部RAM
·32个可编程I/O口线
·3个16位定时/计数器
·7个中断源
·全双工串行UART通道
·低功耗空闲和掉电模式
·中断可从空闲模唤醒系统
·看门狗(WDT)及双数据指针
·掉电标识和快速编程特性
·灵活的在系统编程(ISP字节或页写模式)
AT89S52提供以下标准功能:8k字节Flash闪速存储器,256字节内部RAM,32个I/O口线,看门狗(WDT),两个数据指针,三个16位定时/计数器,一个六向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路。同时,AT89S52可降至0Hz的静态逻辑操作,并支持两种软件可选的节电工作模式。空闲方式停止CPU的工作,但允许RAM,定时/计数器,串行通信口及中断系统继续工作。掉电方式保存RAM中的内容,但振荡器停止工作并禁止其它所有部件工作直到下一个硬件复位。
控制电路设计中采用的是单片机系统,该系统必须要是工作在一个最小系统(指单片机的可以的最小配置系统)。AT89S51的最小系统包括了外界时钟电路和复位电路,选定一定数量的IO口作为控制口控制外部的各种器件和数据的输出。根据功能选择一定的单片机端口添加外围的器件,具体电路如图3所示。
XTAL1(19脚)和XTAL2(18脚)是外接时钟引脚。当采用片内时钟振荡方式时,需要在这两个脚外接石英晶振和振荡电容,石英晶振的频率在0-24MHZ之间,典型值为11.0592MHZ或12MHZ,振荡电容的值一般取10pf-30pf,典型值为30pf。这里石英晶振频率采用11.0592M,振荡电容采用30pf。
RST(9脚)是复位引脚。当输入连续两个机器周期以上的高电平时为有效,用来完成单片机的复位初始化操作。其复位有自动上电复位和人工按钮复位两种。其实图3中的复位电路既能上电自动复位又能人工按钮复位。上电时,电容
两端相当于是短路,于是RST引脚上为高电平,然后电源通过电阻对电容充电,RST端电压慢慢下降,降到一定程度,即为低电平,单片机开始正常工作;当按下按钮时,RST端为高电平,由于按键按下释放时间在数毫秒,所以能够使单片机复位。
EA(31脚)是控制单片机读取内部程序储存器和外部程序储存器的。当EA接高电平时,单片机读取内部程序储存器。当EA接低电平时,单片机直接读取外部ROM。由于89S52有内部程序存储器,所以该引脚接高电平。
图3 AT89S52最小系统
3.2 温度测量模块
3.2.1 温度传感器概述
温度传感器是各种传感器中最常用的一种,早期使用的是模拟温度传感器,如热敏电阻。随着科技的进步,现代温度传感器已经走向数字化,外形小,接口简单,广泛应用在生产实践的各个领域。美国DALLAS半导体公司推出的数字化温度传感器DS18B20采用单总线协议,即与单片机接口仅需占用一个I/O端口,无需任何外部元件,直接将环境温度转化为数字信号,以数字码方式串行输出,从而大大简化了传感器与微处理器的接口。
3.2.2 DS18B20介绍
DS18B20是美国DALLAS半导体公司推出的第一片支持“一线总线”接口的温度传感器,它具有微型化、低功耗、高性能、抗干扰能力强、易配微处理器等优点,可直接将温度转化为串行数字信号供处理器处理。
DS18B20温度传感器特性如下:
① 适应电压范围宽,电压范围在3.0-5.5V,在寄生电源方式下可由数据线供电。
② 特的单线接口方式,它与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通信。
③ 支持多点组网功能,多个DS18B20可以并联在唯一的三线上,实现组网多点测量。
④ 在使用中不需要任何外围器元件,全部传感元件及转换电路集成在形如一只三极管的集成电路内。
⑤ 测温范围-55℃—+125℃,在-10℃—+85℃时精度为±0.5℃。
⑥ 编程分辨率为9-12位,对应的可分辨温度分别为0.5℃、0.25℃、0.125℃和0.0625℃,可实现高精度测温。
⑦ 在9位分辨率时,最多在93.75ms内把温度转换为数字;在12位分辨率时,最多在750ms内把温度转换为数字。
⑧ 测量结果直接输出数字温度信号,以“一线总线”串行传送给CPU,同时可传送CRC校验码,具有极强的抗干扰纠错能力。
⑨ 负压特性。电源极性接反时,芯片不会因发热而烧坏,但不能正常工作。
其应用范围很广,有:
① 冷冻库、粮仓、储罐、电信机房、电力机房、电缆线槽等测温和控制领域。
② 轴瓦、缸体、纺机、空调等狭小空间工业设备测温和控制。
③ 汽车空调、冰箱、冷柜以及中低温干燥箱等。
④ 供热、制冷管道热量计量、中央空调分户热能计量等。
3.2.3 DS18B20与单片机的连接
DS18B20有两种封装:三脚TO-92直插式(用的最多、最普遍的封装)和八脚SOIC贴片式。在此,我们选用三脚TO-92直插式封装的DS18B20芯片。它有三个脚,分别为电源正极VDD、信号输入输出DQ和电源负极GND。
DS18B20是以单总线的方式与单片机相连接的。单总线技术是采用单条信号线,既可传输时钟,又可传输数据,而且数据传输是双向的,因而这种单总线技术具有线路简单,硬件开销少,成本低廉,便于总线扩展和维护等优点。单总线适用于单主机系统,能够控制一个或多个从机设备。单总线通常要求外接一个约为5KΩ的上拉电阻。本系统中采用10KΩ的上拉电阻。本系统DS18B20与单片机的连接如图4所示,DQ与单片机P2.2相连。
图4 DS18B20与单片机的连接
3.3 湿度测量模块
3.3.1 湿度概述
湿度是指大气中的水蒸气的含量,通常采用绝对湿度和相对湿度两种表示方法。绝对湿度是指在一定温度和压力条件下,每单位体积的混合气体中所含水蒸气的质量,单位g/m³,一般用符号AH表示。相对湿度是指气体(通常为空气)的绝对湿度与同一温度下达到饱和状态的绝对湿度的百分比,一般用符号%RH表示。相对湿度给出大气的潮湿程度,它是一个无量纲,在实际应用中多使用相对湿度这一概念。
3.3.2 湿度传感器概述
湿度传感器是能够感受外接湿度变化,并通过器件材料的物理或化学性质变化,将湿度转化成有用信号的器件。
由湿度引起湿度传感器物理或化学变化的种类,可将湿度传感器分为电容式、电阻式和湿涨式。电容式是其高分子材料吸湿后引起介电常数发生变化;电阻式是其高分子材料吸湿后引起电阻率发生变化;湿涨式是其高分子材料吸湿后引起体积发生变化。
通常对湿度传感器有下列要求:在各种气体环境下稳定性好,响应时间短,寿命长,有互换性,耐污染和受温度影响小等。
3.3.3 HS1101湿度传感器介绍
本系统选用HS1101湿度传感器来测量湿度,HS1101是法国Humirel公司推出的一款电容式相对湿度传感器,该传感器广泛应用于办公室、家庭、汽车驾驶室和工业控制系统等,对空气湿度进行监测。与其它湿度传感器相比,它有着显著的优点:
① 无须校验的完全互换性
② 长期饱和状态,瞬间脱湿
③ 适应自动装配过程,包括波峰、焊接、回流焊等
④ 具有高可靠性和长期稳定性
⑤ 特有的固态聚合物结构
⑥ 响应时间快
⑦ 适用于现行电压输出和线形频率输出两种电路
HS1101湿度传感器在电路构成上等效于一个电容器件,采用侧面开放式封装,只有两个引脚,其电容量随着所测空气湿度的增大而增大,但不允许直流方式供电,HS1101湿度传感器外形如图5所示。
图5 HS1101湿度传感器
将HS1101的电容量的变化量准确地转变为单片机易接受的信号的方法,常用有两种:一种是将HS1101置于运放与电容组成的桥式振荡电路中,所产生的正弦波电压信号经整流、直流放大,再由A/D转换为数字信号,供单片机处理;另一种是将HS1101置于555振荡电路中,将电容值的变化转为与之呈反比的电压频率信号,共单片机直接采集和处理。本系统采用555振荡电路的形式。
HS1101与TLC555组成的振荡电路如图6所示。此电路为典型的555非稳态电路。HS1101作为可变电容接在TRIG(2脚)与THRES(6脚)两引脚上。电源电压工作范围是+3.5V-+12V,本系统采用+5V。R3是为了防止输出短路的保护电阻。R4是做内部温度补偿,引入温度效应,使它与HS1101的温度效应相匹配。R4必须为1%精度,最大温度效应小于100ppm的电阻。由于不同型号的555的温度效应不同,所以R4必须与相应型号的555芯片相匹配。为了保证在55%RH的典型湿度值为6660Hz(25℃),R2也必须做修正。对于TLC555,R4取909k,R2取576k。为了使输出方波占空比接近50%,应使R2>>R1,本系统R1取49.9k。
图6 HS1101与555相连的振荡电路
该振荡电路输出的方波的频率fout:
Fout=1/(R1+2R2)C㏑2
根据HS1101使用手册,该振荡电路输出的方波频率范围是6033~7351Hz,所对应的相对湿度为100~0%R。表1给出了一组相对湿度与电压频率的对应值。
表1 相对湿度与电压频率的典型值
%RH
0
10
20
30
40
50
60
70
80
90
100
Hz
7351
7224
7100
6976
6853
6728
6600
6468
6330
6186
6033
输出电压频率与湿度关系为:
其中,fout(55)是指在55%RH的典型湿度值时的电压输出频率值,在25℃下,该值为6660Hz。本系统要求湿度精度为3%RH,可以用下式计算fout与RH的关系:
输出方波的占空比D为:
D=(R1+R2)/(R1+2R2)
由上式可计算出振荡电路输出的方波的占空比为52%。
3.4 LCD显示模块
3.4.1 液晶概述
液晶(Liquid Crystal)是一种高分子材料,因为其特殊的物理、化学、光学特性,20世纪中叶开始广泛应用在轻薄型显示器上。
液晶显示其(Liquid Crystal Display,LCD)的主要原理是以电流刺激液晶分子产生点、线、面并配合背部灯管构成画面。为叙述简便,通常把各种液晶显示器都直接叫做液晶。
各种型号的液晶通常是按照显示字符的行数或液晶点阵的行、列数来命名的。比如:1602的意思是每行显示16个字符,一共可以显示两行;类似的命名还有0801、0802、1601等,这类液晶通常都是字符型液晶,即只能显示ASCII码字符,如数字、大小写字母、各种符号等。还有另一类液晶属于图形型液晶,如12232,它的意思是液晶由122列、32行组成,即共有122×32个点来显示各种图形,我们可以通过程序控制这122×32个点中的任何一个点显示或不显示。类似的命名还有12864、19264、192128、320240等,根据客户需要,厂家可以设计出任意数组合的点阵液晶。
液晶体积小、功耗低、显示操作简单,但是它有个致命的弱点,其使用的温度范围很窄,通用型液晶正常工作温度范围为0℃-+55℃,存储温度范围为-20℃- +60℃,即使是宽温级液晶,其正常工作温度范围也仅为-20℃- +70℃,存储温度范围为-30℃- +80℃。
由于本系统需要显示年月日星期秒分时还有温度,所以用字符型液晶LCD1602足以满足要求。
3.4.2 1602与单片机的连接
1602液晶主要技术参数如下表2所示。
表2 1602液晶主要技术参数表
显示容量
16×2个字符
芯片工作电压
4.5-5.5V
工作电流
2.0mA(5.0V)
模块最佳工作电压
5.0V
字符尺寸
1602液晶引脚功能如表3所示。
表3 1602液晶引脚功能表
引脚号
符号
引脚说明
引脚号
符号
引脚说明
1
Vss
电源地
9
D2
数据口
2
VDD
电源正极
10
D3
数据口
3
VO
液晶显示对比度调节端
11
D4
数据口
4
RS
数据/命令选择端(H/L)
12
D5
数据口
5
R/W
读写选择端(H/L)
13
D6
数据口
6
E
使能信号
14
D7
数据口
7
D0
数据口
15
BLA
背光电源正极
8
D1
数据口
16
BLB
背光电源负极
在设计1602与单片机的接口时,我们将D0-D7八个数据口与P0口相连,但必须注意单片机AT89S52的P0口不带上拉电阻,所以必须附加10K的上拉电阻。由于我们只对液晶进行写液晶指令和数据,而不进行对液晶的读操作,所以R/W(5脚)应接低电平,即接地。其余引脚与单片机的接法如图7所示。
图7 1602与单片机的连接
图7中RS端和E端分别与单片机的P3.0 和P3.1脚相连接。
3.5 电源模块
图8 电源原理图
如图8所示,用220V转12V的变压器进行降压后再通过一个桥式整流电路将交流电整流为直流电。最后通过5V三端稳压模块LM7805得出稳定的5V输出。图14中,电容1是滤波电容,电容2是改善输入电压纹波的;电容3和4是消除高频噪声,增强输出电压稳定的电容。
4 系统软件设计
4.1 DS18B20的操作
要正确操作DS18B20,首先必须了解DS18B20的指令。DS18B20的指令主要包括对ROM操作的指令和对暂存器操作的指令,还有启动温度转换的指令。由于在本系统中,单片机是对一个DS18B20操作,所以就不需要读取ROM编码以及匹配ROM编码了,只要跳过ROM(CCH)命令,随后再启动温度转换(44H)命令,最后便可以通过读暂存器(BEH)命令来读取芯片内部RAM中的9字节的温度数据。
DS18B20在出厂时默认配置为12位,其中最高位为符号位,即温度值共11位,单片机在读取数据时,一次会读2字节共16位,读完后将低11位的二进制数转化为十进制数后再乘以0.0625便为所测的实际温度值。另外,还需要判断温度的正负。前5个数字为符号位,这五位同时变化,我们只需要判断11位就可以了。前5位为1时,读取的温度为负值,且测到的数值需要取反加1再乘以0.0625才可得到实际温度值。前五位为0时,读取的温度为正值,且温度为正值时,只要将测得的数值乘以0.0625即可得到实际的温度值。
由于DS18B20 是在一根I/O 线上读写数据,因此,对读写的数据位有着严格的时序要求。DS18B20 有严格的通信协议来保证各位数据传输的正确性和完整性。该协议定义了几种信号的时序:初始化时序、读时序、写时序。所有时序都是将主机作为主设备,单总线器件作为从设备。而每一次命令和数据的传输都
是从主机主动启动写时序开始,如果要求单总线器件回送数据,在进行写命令后,主机需启动读时序完成数据接收。数据和命令的传输都是低位在先。
DS18B20的工作时序见以下各图:
(1) DS18B20初始化
图9 DS18B20初始化时序图
① 先将数据线置高电平1。
② 延时(改时间要求不是很严格,但是要尽可能短些)。
③ 数据线拉到低电平0。
④ 延时750us(该时间范围可以在480-960us)。
⑤ 数据线拉到高电平1。
⑥ 延时等待。如果初始化成功则在15-60us内产生一个由DS18B20返回的低电平0,据该状态可以确定它的存在。但是应该注意,不能无限的等待,不然会使程序进入死循环,所以要进行超时判断。
⑦ 若CPU读到数据线上的低电平0后,还要进行延时,其延时的时间从发出高电平算起(第⑤步)最少要480us。
⑧ 将数据线再次拉到高电平1后结束。
(2) DS18B20写数据
对于DS18B20 的写时序仍然分为写0 时序和写1 时序两个过程。
对于DS18B20 写0 时序和写1 时序的要求不同,当要写0 时序时,单总线要被拉低至少60us,保证DS18B20 能够在15us 到45us 之间能够正确地采样IO 总线上的“0”电平,当要写1 时序时,单总线被拉低之后,在15us 之内就得释放单总线。
图10 DS18B20写数据时序图
写1步骤:
① 数据线先置低电平0。
② 延时4us(该值应小于15us)。
③ 数据线置高。
④ 延时66us。
写0步骤:
① 数据线先置低电平0。
② 延时70us(该延时原则上应大与60us)。
③ 数据线置高。
(3) DS18B20读数据
对于DS18B20 的读时序分为读0 时序和读1 时序两个过程。
对于DS18B20 的读时隙是从主机把单总线拉低之后,在15 秒之内就得释放单总线,以让DS18B20把数据传输到单总线上。DS18B20 在完成一个读时序过程,至少需要60us 才能完成。
图11 DS18B20读数据时序图
① 数据线拉到低电平0。
② 延时4us(该值应大于1us小于15us)。
③ 数据线拉到高电平1。
④ 延时8us。
⑤ 读数据线的状态得到一个状态位,并进行数据处理。
⑥ 延时400us。
⑦ 重复①-⑦步骤,直到读取完一个字节。
4.2 1602的操作
1.基本操作时序
读状态 输入:RS=L,R/W=H,E=H
输出:D0-D7=状态字
读数据 输入:RS=H,R/W=H,E=H
输出:无
写指令 输入:RS=L,R/W=L,D0-D7=指令码,E=高脉冲 输出:D0-D7=数据
写数据 输入:RS=H,R/W=L,D0-D7=数据, E=高脉冲 输出:无
2.RAM地址映射图
控制器内部带有80B的RAM缓冲区,对应关系如图12所示。
00
01
02
03
04
05
06
07
08
09
0A
0B
0C
0D
0E
0F
10
…
27
40
41
42
43
44
45
46
47
48
49
4A
4B
4C
4D
4E
4F
50
…
67
图12 1602内部RAM地址映射图
当我们向图10中的00-0F、40-4F地址中的任一处写入显示数据时,液晶都可以立即显示出来,当写到10-27或50-67地址时,必须通过移屏指令将它们移入可显示区域方可正常显示。
3.状态字说明
1602含8个状态字,分别为STA0(D0)-STA7(D7)。STA0-STA6表示当前地址指针的数值,STA7表示读/写使能,当STA7=1时,静止读写;当STA7=0时,允许读写。原则上每次对控制器进行读/写操作之前,都必须进行读/写检测,确保STA7为0。但实际上,由于单片机的操作速度慢于液晶控制器的反应速度,因此可以不进行读/写检测,或只要进行简短的延时即可。
4.数据指针设置
1602控制器内部设有一个数据地址指针,用户可以通过他们访问内部80B的RAM,设置数据地址指针的指令码为:80H+地址码(0-27H,40-67H)。
5.其他设置
见表4。
表4 其他设置
指令码
功能
01H
显示清屏:1.数据指针清0
2.所有显示清0
02H
显示回车:数据指针清0
6.初始化设置
(1)显示模式设置
见表5。
表5 显示模式设置
指令码
功能
38H
设置16×2显示,5×7点阵,8位数据接口
(2)显示开/关及光标设置
见表6。
表6 显示开/关及光标设置
指令码
功能
0
0
0
0
1
D
C
B
D=1 开显示;D=0 关显示
C=1 显示光标;C=0 不显示光标
B=1 光标闪烁;B=0 光标不闪烁
0
0
0
0
0
1
N
S
N=1 当读或写一个字符后地址指针加1,且光标加1
N=0当读或写一个字符后地址指针减1,且光标减1
S=1 当写一个字符时,整屏显示左移(N=1)或右移(N=0),以得到光标不移动而屏幕移动的效果
S=0 当写一个字符时,整屏显示不移动
0
0
0
1
0
0
0
0
光标左移
0
0
0
1
0
1
0
0
光标右移
0
0
0
1
1
0
0
0
整屏左移,同时光标跟随移动
0
0
0
1
1
1
0
0
整屏右移,同时光标跟随移动
7.写操作时序
见图13。
图13 1602液晶写操作时序图
分析时序图可知操作1602液晶的流程如下:
⑴ 通过RS确定是写数据还是写命令。写命令包括使液晶的光标显示/不显示、光标闪烁/不闪烁、需/不需要移屏、在液晶什么位置显示,等等。写数据是指要显示什么内容。
⑵ 读/写控制端设置为写模式,即低电平。
⑶ 将数据或命令送达数据线上。
⑷ 给E一个高脉冲将数据送入液晶控制器,完成写操作。
关于时序图中的各个延时,不同厂家生产的液晶的延时不同,大多数基本为纳秒级,单片机操作的最小单位为微妙级,因此在写程序时可不做延时,不过为了使液晶运行稳定,最好做简短的延时。其最佳延时时间要测试得出。
4.3 湿度测量软件
湿度传感器测量得到的数据信号经555振荡电路后输出方波,再将方波信号进入单片机AT89S52的T0引脚,T0工作在计数方式,T1工作在定时方式。在T1定时1秒的时间内,T0所计得的数值即为方波信号的频率值。求出方波的频率,根据前面555振荡电路中输出电压频率与湿度的关系式,进而得到相对湿度。
附录一 系统电路图
附录二 源程序
#include
#define uint unsigned int
#define uchar unsigned char
sbit rs=P3^0;//液晶控制端
sbit en=P3^1;
sbit ds=P2^2;//18B20的信号线
uint temp;//定义整形的温度数据
float f_temp;//定义浮点型的温度数据
uchar hum;//定义整形的湿度数据
float f_hum;//定义浮点型的湿度数据
uchar T1_count,T0_count;
bit flag,minus_flag;
//*******************************延时函数*****************************//
void delayms(uint xms)//延时函数
{
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
//*******************************ds18B20处理函数***********************//
bit dsreset(void) //18B20复位,初始化函数
{
uchar i;
ds=0;
for(i=255;i>0;i--);//uchar型数做一次加减运算为大概2us,uint型大约为4us
ds=1;
for(i=60;i>0;i--);
return(ds);
for(i=200;i>0;i--);
}
bit tempreadbit(void) //读1位函数
{
uchar i;
bit dat;
ds=0;
for(i=2;i>0;i--);
ds=1;
for(i=4;i>0;i--);
dat=ds;
for(i=200;i>0;i--);
return (dat);
}
uchar tempread(void) //读1个字节
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tempreadbit();
dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里
}
return(dat);
}
void tempwritebyte(uchar dat) //向18B20写一个字节数据
{
uchar i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) //写 1
{
ds=0;
for(i=2;i>0;i--);
ds=1;
for(i=33;i>0;i--);
}
else
{
ds=0; //写 0
for(i=35;i>0;i--);
ds=1;
}
}
}
void tempchange(void) //DS18B20 开始获取温度并转换
{
uchar i;
while(dsreset()==1&&(i<255))// 超时判断
i++;
tempwritebyte(0xcc); // 写跳过读ROM指令
tempwritebyte(0x44); // 写温度转换指令
}
uint get_temp() //读取寄存器中存储的温度数据
{
uchar a,b,i;
while(dsreset()==1&&(i<255))// 超时判断
i++;
tempwritebyte(0xcc);
tempwritebyte(0xbe);
a=tempread(); //读低8位
b=tempread(); //读高8位
temp=b;
if(b==0) //温度为正
{
temp<<=8; //两个字节组合为1个字
temp=temp|a;
minus_flag=0;
}
else //温度为负
{
temp<<=8;
temp=temp|a;
temp=(~temp)+1;
minus_flag=1;
}
f_temp=temp*0.0625; //温度在寄存器中为12位 分辨率位0.0625
temp=f_temp*10+0.5; //乘以10表示小数点后面只取1位,加0.5是四舍五入
return temp; //temp是整型
}
//*******************************湿度计算函数********************************//
uchar get_hum()
{
uint fre_count;
if(flag==1)
{
flag=0;
fre_count=T0_count*65536+TH0*256+TL0;
f_hum=(float)(7351-fre_count)/1256.0;
hum=f_hum*100+0.5;
T1_count=0;
TH1=(65536-45872)/256;//重装初值
TL1=(65536-45872)%256;
T0_count=0;
TH0=0;
TL0=0;
TR0=1;
TR1=1;
}
return hum;
}
//*******************************lcd1602处理函数*****************************//
void write_com(uchar com)//写液晶命令函数
{
rs=0;
P0=com;
delayms(5);
en=0;
en=1;
delayms(5);
en=0;
}
void write_date(uchar date)//写液晶数据函数
{
rs=1;
P0=date;
delayms(5);
en=0;
en=1;
delayms(5);
en=0;
}
void wr_Char(unsigned char x,unsigned char y, unsigned char c)//往第y行的第x列写字符c
{
if(y==0)
write_com(0x80+x);
else if(y==1)
write_com(0xc0+x);
else if(y>1){}
write_date(c);
delayms(5);
}
void lcd_init()//液晶初始化函数
{
write_com(0x38);//设置16X2显示,5X7点阵,8位数据接口
write_com(0x0c);//设置开显示,不显示光标
write_com(0x06);//写一个字符后地址指针加1
write_com(0x01);//显示清零,数据指针清0,即显示清屏
wr_Char(3,0,'T');//写液晶固定显示部分
wr_Char(12,0,'H');
wr_Char(3,1,'.');
wr_Char(5,1,0xdf);//液晶字符°的字型码为0xdf
wr_Char(6,1,0x43);//液晶字符C的字型码为0x43
wr_Char(12,1,0x25);//"%"
wr_Char(13,1,'R');
wr_Char(14,1,'H');
}
//*******************************定时器T0和T1初始化函数**************//
void Timer_init()
{
TMOD=0x15;//T0作为计数器使用,模式1;T1作为定时器使用,模式1.
TH0=0; //T0计数值清零
TL0=0;
TH1=(65536-45872)/256;//50ms初值
TL1=(65536-45872)%256;
EA=1;
ET0=1;
ET1=1;
TR1=1;
TR0=1;
}
//*******************************温度/湿度显示函数*******************//
void dis_temp(uint t,uchar h)//用液晶显示温度/湿度的函数
{
uchar bai,shi,ge;
uchar shi1,ge1;
bai=t/100; //显示温度
shi=t%100/10;
ge=t%100%10;
if(minus_flag==1)
{
minus_flag=0;
wr_Char(0,1,'-');
}
else
wr_Char(0,1,' ');
wr_Char(1,1,0x30+bai);
wr_Char(2,1,0x30+shi);
wr_Char(4,1,0x30+ge);
shi1=h/10; //显示湿度
ge1=h%10;
wr_Char(10,1,0x30+shi1);
wr_Char(11,1,0x30+ge1);
}
//*******************************主函数*****************************//
void main()
{
uint temp_value;
uchar hum_value;
Timer_init();//定时器初始化
lcd_init();//液晶初始化
while(1)
{
tempchange();
temp_value=get_temp();
hum_value=get_hum();
dis_temp(temp_value,hum_value);
}
}
//*******************************T0溢出中断服务程序********************//
void T0_Timer(void) interrupt 1
{
T0_count++;
}
//*******************************T1定时中断服务程序*********************//
void T1_Timer(void) interrupt 3
{
TH1=(65536-45872)/256;//重装初值
TL1=(65536-45872)%256;
T1_count++;
if(T1_count==20)//1s到
{
TR0=0;//停止T0
TR1=0;//停止T1
T1_count=0;
flag=1;
}
}
微控制器 模块
晶振
电源
复位电路
温度传感器
LCD显示电路
湿度传感器
振荡电路
LCD
16字×2行
定时器T0、T1初始化;LCD1602初始化
开始转换温度并获取温度值
获取湿度值
显示温度值和湿度值
_1296672039.unknown
_1296675249.unknown