小型智能系统设计-------
实验项目报告
实验名称:基于STC 89C52单片机的温湿度变送器
实验日期: 2014年5月——2014年6月
院 系:电子科学与工程学院 专 业: 微电子科学与工程
指导老师:张 熠
姓 名:高 波 学 号:B13020927 EDA实验室
开课时间:2013/2014 学年 第二学期
摘要
随着人们生活水平的不断提高,利用单片机实现智能控制无疑是人们追求的目标之一,它给人带来的方便也是毋庸置疑的,其中温度传感器就是其中的一个典型例子,但是人们对单片机的控制要求越来越高。要为现代人工作,生活,科研,学习提供更好、更方便、更人性化的设施就要从单片机技术入手,一切向数字化、智能控制化方向发展。
温湿度变送器基于STC 89C52 单片机,配以DHT11传感器、DS1302显示器以及RS485中继站,具有精度高、适用范围广、生产加工简单、成本低、支持远距离传送、操作简单等优点。是工农业生产和日常生活都非常实用的一种器件。
- 2 -
目 录
序 言 ……………………………………………………………3 第一章 温度采集器总体设计方案………………………………4 1.0 温度采集器设计方案论述……………………………4
1.1 方案明细…………………………………………………4
第二章 硬件设计………………………………7 2.0 1-wire总线协议介绍…………………………………7 2.1 STC89C52的简单介绍………………………8 2.2 DHT11特点及电气特性………………………9 2.3 MAX232特点及电气特性………………………………10 2.4 11.0592晶体振荡器电气特性………………………13 第三章 系统软件设计………………………………………………13 3.0 主程序设计…………………………………13 3.1 温度程序设计(DHT11模块)………………………13 3.2 时间程序设计(DS1302模块)…………………14 第四章 总结与体会…………………………………………14 第五章 软件仿真与系统调试……………………………………16 5.0 protues软件仿真……………………………………19 5.1 keil version仿真 ……………………………………25 5.2 实物照片 ……………………………………29 第六章 附录 ……………………………………29 6.0 主程序源代码 ……………………………………30
- 3 -
序 言
智能温度传感器 智能温度传感器(亦称数字温度传感器)是在20世纪90年代中期问世的。它是微电子技术、计算机技术和自动测试技术(ATE_)的结晶。目前,国际上已开发出多种智能温度传感器系列产品。智能温度传感器内部包含温度传感器、A/D传感器、信号处理器、存储器(或寄存器)和接口电路。有的产品还带多路选择器、中央控制器(CPU)、随机存取存储器(RAM)和只读存储器(ROM)。 智能温度传感器能输出温度数据及相关的温度控制量,适配各种微控制器(MCU),并且可通过软件来实现测试功能,即智能化取决于软件的开发水平。
温室能在不适宜植物生长的季节,为植物提供生育期和增加产量。影响植物生长有多种因素,其中包括温度、湿度、照度这三个重要因素。不适宜的温、湿、照度不仅会阻碍植物生长、影响植物繁殖,也会使病虫害迅速扩散繁殖。因此必须合理控制温室的温、湿、照度,促进作物健康生长,抑制病虫危害,提高作物产量,增加经济效益。
目前,绝大多数的温室使用温度计、干湿球湿度计,采用人工观测的方法。这种方法的特点是简单,设备成本很低。缺点是实时性差,检测相对湿度的精度太低,人工工作量大。
而此项设计与传统的数字温度计相比,具有读数方便、测温范围广、测温精度高的优点,尤其是温度采用数字显示,设计更加的人
- 4 -
性化。设计所需元件,无论是STC89C52单片机,还是测温、湿度所需的DHT11传感器、时钟芯片DST1302、1602A液晶显示器都是市场上所常见的电子元件,设计成本低廉,精度高非常适合生产。
再加以RS485作为中继站,就可以实现对温湿度的远距离传输和数据采集,大大减少了人力物力的投入,提高了工农业现代化水平。
第一章 温度采集器系统设计方案
1.0 温湿度采集器设计原理
由于本设计是测温湿度电路,可以使用热敏电阻之类的器件利
用其感温效应,在将随被测温变化的电压或电流采集过来,进行A/D转换后,可以利用单片机进行数据处理,在显示电路上,就可以将被测温度显示出来,这种设计需要利用到A/D转换电路,感温电路比较麻烦。进而考虑到可以利用温湿度传感器,在单片机电路设计中,大多是使用传感器,所以这是非常容易想到的,所以采用DLLAS的DHT11,由此传感器,可以容易的直接读取被测温湿度值,进而进行转换就可以满足设计要求,以上两种设计思路,通过优劣比较,可以发现DHT11的设计思路比较简单,易于电路设计与焊接,故采用第二种方案。
温度传感器的电路设计方框图如图1所示,控制器采用单片机STC89C52,温湿度传感器采用DHT11,用户可以通过显示器读出实时
- 5 -
温度、湿度值,单片机与MAX232相连,可以把TTL电平转化为计算机读取的RS-232电平,然后可以通过9针串行通信口与计算机相连,把读到的数据存储在计算机内。再加以RS-485作为中继站,就可以实现对温湿度的远距离传输和数据采集。方便用户随时调阅并进行数据分析。
1 .1 温湿度传感器的总体设计框图
MAX232 主 控 制 器 9针通信串 口 CPU STC89C52 PC 晶体振荡器 ............. RS485
1602A液晶显示DHT11传感器 DST302时钟芯片 LED工作指示灯、 蜂鸣器 PC 图1:硬件总体设计框图
- 6 -
第二章 硬件设计
2.0 STC89C52的简单介绍
端口引脚 第二功能:
P1.0 T2 (定时器/计数器T2的外部计数输 入),时钟输出
P1.1 T2EX(定时器/计数器T2的捕捉/重载触发信号和方向控制)
P1.5 MOSI(在线系统编程用) P1.6 MISO(在线系统编程用) P1.7 SCK(在线系统编程用) P3.0 RXD(串行输入口) P3.1 TXD(串行输出口) P3.2 INTO(外中断0) P3.3 INT1(外中断1) P3.4 TO(定时/计数器0) P3.5 T1(定时/计数器1)
P3.6 WR(外部数据存储器写选通) P3.7 RD(外部数据存储器读选通) 此外,P3口还接收一些用于FLASH闪存编 程和程序校验的控制信号。
图2 STC89C52 管脚图
STC89C52的主要性能
STC89C52与MCS-51单片机产品兼容 、8K字节在系统可编程Flash存储器、 1000次擦写周期、全静态操作:0Hz~33Hz 、三级加密程序存储器 、 32个可编程I/O口线 、三个16位定时器/计数器八个中断源、全双工UART串行通道、 低功耗空闲和掉电模式 、掉电后中断可唤醒 、看门狗定时器 、双数据指针 、掉电标识符 。
- 7 -
2.1 DHT11特点及电气特性
①DHT11实物图
①DHT11产品概述
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性和卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个DHT11传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式存在OTP内存中,传感器内部在检测型号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,使其成为给类应用甚至最为苛刻的应用场合的最佳选择。产品为4针单排引脚封装,连接方便。 ②DHT11与单片机的接线图
- 8 -
引脚说明
1pin:VDD 用于供电3-5.5VDC
2pin: DATA 串行数据,单总线 3pin: NC 空脚,请悬空 4pin: GND 接地,电源负极 ②DHT11技术参数 供电电压: 3.3~5.5V DC 输 出: 单总线数字信号 测量范围: 湿度20-90%RH, 温度0~50℃ 测量精度: 湿度+-5%RH, 温度+-2℃ 分 辨 率: 湿度1%RH, 温度1℃ 互 换 性: 可完全互换 , 长期稳定性: <±1%RH/年 ③电气特性 VDD=5V,T = 25℃,除非特殊标注 参数 供电 供电电流 条件 DC 测量 平均 待机 采样周期 秒 min 3 0.5 0.2 100 1 typ 5 max 5.5 2.5 1 150 单位 V mA mA uA 次 - 9 -
④详细参数 参数 湿度 分辨率 重复性 精度 0-50℃ 互换性 量程范围 25℃ 50℃ 响应时间 迟滞 长期稳定性 温度 分辨率 8 重复性 精度 量程范围 响应时间 1/e(63%) ±1 0 6 1 8 1 8 ±1 Bit 1 ±2 50 30 ℃ ℃ ℃ ℃ S 25℃ 可完全互换 0℃ 20 20 1/e(63%)25℃,1m/s 空气 典型值 6 10 ±1 ±1 15 S %RH %RH/yr 30 90 80 90 %RH %RH %RH 1 8 1 ±1 ±4 ±5 Bit 1 %RH %RH %RH %RH 条件 Min Typ Max 单位 ⑤DHT11主要优点 能够进行相对湿度和温度测量 全部校准,数字输出 卓越的长期稳定性 无需额外部件 超长的信号传输距离 超低能耗 4引脚安装 完全互换 ⑥DHT11工作原理
- 10 -
2.2 Max232特点及电气特性
图6 MAX232管脚图
①MAX232原理
MAX232芯片是专门为电脑的RS-232标准串口设计的接口电路,使用+5v单电源供电。
内部结构基本可分三个部分:
第一部分是电荷泵电路。由1、2、3、4、5、6脚和4只电容构成。功能是产生+12v和-12v两个电源,提供给RS-232串口电平的需要。
第二部分是数据转换通道。由7、8、9、10、11、12、13、14脚构成两个数据通道。其中13脚(R1IN)、12脚(R1OUT)、11脚 (T1IN)、14脚(T1OUT)为第一数据通道。8脚(R2IN)、9脚(R2OUT)、10脚(T2IN)、7脚(T2OUT)为第二数据通道。TTL/CMOS数据从T1IN、T2IN输入转换成RS-232数据从T1OUT、T2OUT送到电脑DP9插头;DP9插头的RS-232数据从 R1IN、R2IN输入转换成TTL/CMOS数据后从R1OUT、R2OUT输出。
第三部分是供电。15脚DNG、16脚VCC(+5v)。
2.3 11.0592晶体振荡器电气特性
在使用串口做通信时,一个很重要的参数就是波特率,只有上下位机的波特
- 11 -
率一样时才可以进行正常的通信。波特率是指串行端口每秒内可以传输的波特位数。可以用以下的公式计算波特率:
波特率=(2sMMOd/32)*定时器1溢出速率 上述公式中设置了PCON寄存器中的SMOD位为1时就可以把波特率提升2倍。通常会使用定时器1工作在定时器工作模式2下,这时定时值下的TL1作为计数,TH1作为自动重装值,在这个定时模式下,定时器溢出后,TH1的值会自动重装到TL1,再次开始计数,这样可以不用软件去干预,使得定时更准确。在这个定时模式二下定时器1溢出速率计算公式如下:
溢出速率=计数速率/(256-TH1)
上式中的“计数速率”与所使用的晶体振荡器频率有关,在51芯片中定时器启动后会在每一个机器周期使用定时寄存器TH的值增加1,一个机器周期等于12个振荡周期,作用可以得知51芯片的技术速率为晶体振荡频率的1/12,一个12M的晶振使用在51芯片上,那么51芯片的计数速率就为1M。通常11.0592M晶体是为了得到标准无误差的波特率
2.4 MAX485 DATASHEET,电路图内容介绍:
MAX485是用于RS-485与RS-422通信的低功耗收发器,每个器件中都具有一个驱动器和一个接收器。MAX485的驱动器摆率不受限制,可以实现最高2.5Mbps的传输速率。这种收发器在驱动器禁用的空载或满载状态下,吸取的电源电流在120(A 至500(A 之间。 驱动器具有短路电流限制,并可以通过热关断电路将驱动器输出置为高阻状态,防止过度的功率损耗。接收器输入具有失效保护特性,当输入开路时,可以确保逻辑高电平输出。
- 12 -
MAX485引脚(管脚)图及工作电路
第三章 系统软件设计
3.0
系统软件的主程序是调用子程序的,它是所有子程序在功能上的汇总,是整个程序的“首脑”,CPU是从从主程序开始读程序的,所以主程序的设计尤为重要。这个系统软件的主程序主要完成温度在4位8段的数码管上显示温度的功能。主程序设计如下:
3.1 温度程序设计(DS18B20模块)
3.2 时间程序设计(DS1302模块)
4.时间程序设计模块在某些方面与温度设计模块具有很大的相似性,在这里主要介绍一下,其中的显示程序(具体详细程序参见附录后的详细程序清单)。 void ds1302_display(void) //显示时分 {
P2=0xf7; //P2负责位选 P0=tab[shi/16];//P0负责段选 delay();
- 13 -
P2=0xfb; P0=tab[shi%16]; delay(); P2=0xfd; P0=tab[fen/16]; delay(); P2=0xfe; P0=tab[fen%16]; delay(); }
第四章 总结与体会
本次试验,通过设计焊接一个温度传感器,让我们对单片机的基本知识有了一个大致的了解,同时也引起了我们对单片机的兴趣。学习单片机知识是一个软硬结合的学习过程。在实际做这个试验时,我们遇到的困难有硬件连线方面的,也有软件设计方面的。比如在设计软件时,由于对单片机C语言一窍不通,所以在设计软件的时候显得分外掣肘,无从下手。这时候,通过看书和上网查阅相关的资料,我们了解了一些单片机C语言的基础知识,这时候,虽然还是写不出一个完整而准确、可运行的单片机C程序,但是,我们已经可以基本的看懂书本上和网上提供的源程序了。再比如硬件方面,试验中所使用的元器件,无论是单片机STC89C52,还是温度传感元件DHT11,我们都对它们没有任何的了解,更谈不上连线了,这时候,上网是一个很不错的方法,网上提供了很多这样的例子,尽管不完全相同,但作为参考已足够了。
这次实验,我觉得收获最大的,既不是对单片机的了解,也不是对动手能力的提高,固然,这两点都是十分重要的。但是,我觉得,还有比这更加重要的,那就是解决问题的方法。一个问题可以有千万种方法解决,但是要在这千万种方法中找到最合适的,是比较困难的,因为每个人的方法都不尽相同,而且受到各
- 14 -
种条件的约束,找到自己合适的方法就更困难了。在本次的试验中,我们面临着时间与知识的双重考验。首先由于时间原因,我们不能花大把大把的时间在这项实验上面,这是十分可惜的。其次,我们缺少单片机方面的知识。所以,我们可以依靠的最强大的力量就是图书馆和网络了,这两者都具备各自的优势,图书馆的资源更加准确,网络则更加方便,结合两种,就可以做到最好。于是,我们一方面寻求来自图书馆的图书帮助,通过翻阅单片机的相关资料,对单片机的知识有了一个大概的了解,然后通过网络上的论坛找到了一些相关的实例,通过分析实例,然后再设计自己的电路和系统软件,这样,双管齐下,事半功倍。同时,对于这次的开放性试验,我也体会到了团队合作的重要性与必要性,中国古语:众人拾柴火焰高,面对一个难题,我们固然是要具备独立思考的能力,但是也不能忽略团队合作的重要意义。通过分工协作,纵然是很大的困难,也能将它分成若干模块,分工到个人,最后再交流总结。这样,我们就能很好的解决问题了。在面对巨大难题的时候,团队合作就显得尤为重要。其次,通过这次的实验,我也感觉到了自己在动手方面的不足与欠缺。这需要我在今后的学习中努力锻炼自己的动手能力。同时,我也深刻的认识到了“谋定而后动”的重要性。我们搭完电路,仿真通过,但是这还没有结束,因为实际的硬件连线与在仿真软件上搭电路是不能相提并论的,在实际的硬件连线中,需要我们考虑的因素更多,更复杂。这需要我们在动手之前,仔细的规划好硬件布局,然后再进行焊接。
唯有实践方能出真知,这次做的产品给我们上了一次很生动的课。总的来说 这次实践,我们学到许多,不仅仅是书本或者是网上的资料给我们的知识,更重要的是动手实践后的体会,感悟。
- 15 -
第五章 软件仿真与系统调试
5.0 软件仿真 protues8.0
未启动调试按钮之前
- 16 -
启动调试按钮:显示默认温湿度: TEMP(温度):26.9 Huni(湿度):45.3%
- 17 -
点击DHT11中的加减按钮增加温度,后选择shift,增加湿度: TEMP(温度):26.9C Huni(湿度):87.6%
- 18 -
STC89C52 单片机工作状态,以及引脚使用情况。
- 19 -
DS1602液晶显示器
- 20 -
九孔通用串口模拟仿真以及引脚使用情况
- 21 -
DHT11温湿度传感器模拟仿真图
- 22 -
5.1 keil version4软件仿真图
- 23 -
- 24 -
- 25 -
- 26 -
5.2 实物照片
去掉显示器的内部结构
- 27 -
整体实物图
第六章 附录
附录:程序代码
//DS1602程序(1602.c): #include ************************************************************** unsigned char LCD_Wait(void) { LcdRs=0; LcdRw=1; _nop_(); LcdEn=1; _nop_(); - 28 - LcdEn=0; return DBPort; } //向LCD写入命令或数据 ******************************************************** #define LCD_COMMAND 0 // Command #define LCD_DATA 1 // Data #define LCD_CLEAR_SCREEN 0x01 // 清屏 #define LCD_HOMING 0x02 // 光标返回原点 void LCD_Write(bit style, unsigned char input) { LcdEn=0; LcdRs=style; LcdRw=0; _nop_(); DBPort=input; _nop_();//注意顺序 LcdEn=1; _nop_();//注意顺序 LcdEn=0; _nop_(); LCD_Wait(); } //设置显示模式 ************************************************************ #define LCD_SHOW 0x04 //显示开 #define LCD_HIDE 0x00 //显示关 #define LCD_CURSOR 0x02 //显示光标 #define LCD_NO_CURSOR 0x00 //无光标 #define LCD_FLASH 0x01 //光标闪动 - 29 - #define LCD_NO_FLASH 0x00 //光标不闪动 void LCD_SetDisplay(unsigned char DisplayMode) { LCD_Write(LCD_COMMAND, 0x08|DisplayMode); } //设置输入模式 ************************************************************ #define LCD_AC_UP 0x02 #define LCD_AC_DOWN 0x00 // default #define LCD_MOVE 0x01 // 画面可平移 #define LCD_NO_MOVE 0x00 //default void LCD_SetInput(unsigned char InputMode) { LCD_Write(LCD_COMMAND, 0x04|InputMode); } //初始化 LCD************************************************************ void LCD_Initial() { LcdEn=0; LCD_Write(LCD_COMMAND,0x38); //8位数据端口,2行显示,5*7点阵 LCD_Write(LCD_COMMAND,0x38); LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标 - 30 - LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏 LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动 } //液晶字符输入的位置************************ void GotoXY(unsigned char x, unsigned char y) { if(y==0) LCD_Write(LCD_COMMAND,0x80|x); if(y==1) LCD_Write(LCD_COMMAND,0x80|(x-0x40)); } //将字符输出到液晶显示 void Print(unsigned char *str) { while(*str!='\\0') { LCD_Write(LCD_DATA,*str); str++; } } //SHT10程序(SHT10.c): #include //继续传输数据,用于判断是否结束通讯 #define ACK 1 //结束数据传输, //地址 命令 读/写 #define STATUS_REG_W 0x06 //000 0011 0 #define STATUS_REG_R 0x07 //000 0011 1 - 31 - #define MEASURE_TEMP 0x03 //000 0001 1 #define MEASURE_HUMI 0x05 //000 0010 1 #define RESET 0x1e //000 1111 0 //写字节程序 char s_write_byte(unsigned char value) { 发送的位 讯正常 } //读字节程序 char s_read_byte(unsigned char ack) //---------------------------------------------------------------------------------- _nop_();_nop_();_nop_(); SCK=0; DATA=1; return error; //error=1 通讯错误 else DATA=0; SCK=1; _nop_();_nop_();_nop_(); //延时3us SCK=0; } DATA=1; //释放数据线 SCK=1; error=DATA; //检查应答信号,确认通unsigned char i,error=0; for (i=0x80;i>0;i>>=1) //高位为1,循环右移 { if (i&value) DATA=1; //和要发送的数相与,结果为 - 32 - { unsigned char i,val=0; DATA=1; //释放数据线 for(i=0x80;i>0;i>>=1) //高位为1,循环右移 { SCK=1; if(DATA) val=(val|i); // SCK=0; } DATA=!ack; //结束通讯; SCK=1; _nop_();_nop_();_nop_(); // SCK=0; _nop_();_nop_();_nop_(); DATA=1; // return val; } //启动传输 void s_transstart(void) // generates a transmission start // _____ ________ // DATA: |_______| // ___ ___ // SCK : ___| |___| |______ { DATA=1; SCK=0; // _nop_(); SCK=1; - 33 - 读一位数据线的值 如果是校验,读取完后 延时3us 释放数据线 准备 } //连接复位 _nop_(); DATA=0; _nop_(); SCK=0; _nop_();_nop_();_nop_(); SCK=1; _nop_(); DATA=1; _nop_(); SCK=0; void s_connectionreset(void) // communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart // _____________________________________________________ ________ // DATA: |_______| // _ _ _ _ _ _ _ _ _ ___ ___ // SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______| |___| |______ { unsigned char i; DATA=1; SCK=0; //准备 for(i=0;i<9;i++) //DATA保持高,SCK时钟 触发9次,发送启动传输,通迅即复位 { - 34 - } //软复位程序 SCK=1; SCK=0; } s_transstart(); //启动传输 char s_softreset(void) // resets the sensor by a softreset { } /*读状态寄存器 char s_read_statusreg(unsigned char *p_value, unsigned char *p_checksum) //---------------------------------------------------------------------------------- // reads the status register with checksum (8-bit) { sensor (8-bit) (8-bit) return error; //error=1 in case of no *p_checksum=s_read_byte(noACK); //read checksum *p_value=s_read_byte(ACK); //read status register unsigned char error=0; s_transstart(); //transmission start error=s_write_byte(STATUS_REG_R); //send command to unsigned char error=0; s_connectionreset(); //启动连接复位 error+=s_write_byte(RESET); //发送复位命令 return error; //error=1 通讯错误 - 35 - response form the sensor } //写状态寄存器 char s_write_statusreg(unsigned char *p_value) // writes the status register with checksum (8-bit) { sensor register return error; //error>=1 in case of error+=s_write_byte(*p_value); //send value of status unsigned char error=0; s_transstart(); //transmission start error+=s_write_byte(STATUS_REG_W);//send command to no response form the sensor } //温湿度测量 char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode) // 进行温度或者湿度转换,由参数mode决定转换内容; { // { case TEMP : error+=s_write_byte(MEASURE_TEMP); break; //测量温度 enum {TEMP,HUMI}; unsigned error=0; unsigned int i; s_transstart(); //启动传输 switch(mode) //选择发送命令 //已经在头文件中定义 */ - 36 - case HUMI : error+=s_write_byte(MEASURE_HUMI); break; //测量湿度 default : break; } for (i=0;i<65535;i++) if(DATA==0) break; //等待测量结束 if(DATA) error+=1; // 如果长时间数据线没 有拉低,说明测量错误 (MSB) (LSB) } //温湿度值标度变换及温度补偿 void calc_sth10(float *p_humidity ,float *p_temperature) { 公式 公式 公式 件 修正公式 件 修正公式 float rh=*p_humidity; // rh: 12位 湿度 float t=*p_temperature; // t: 14位 温度 const float T2=+0.00008; // 14位温度精度 5V条const float T1=+0.01; // 14位温度精度 5V条const float C3=-0.0000028; // 12位湿度精度 修正const float C2=+0.0405; // 12位湿度精度 修正const float C1=-4.0; // 12位湿度精度 修正*p_checksum =s_read_byte(noACK); //read CRC校验码 return error; // error=1 通讯错误 *(p_value+1)=s_read_byte(ACK); //读第二个字节,低字节 *(p_value) =s_read_byte(ACK); //读第一个字节,高字节 - 37 - 值 值 度依赖性补偿 } float rh_lin; // rh_lin: 湿度 linear float rh_true; // rh_true: 湿度 ture float t_C; // t_C : 温度 ℃ t_C=t*0.01 - 40; //补偿温度 rh_lin=C3*rh*rh + C2*rh + C1; //相对湿度非线性补偿 rh_true=(t_C-25)*(T1+T2*rh)+rh_lin; //相对湿度对于温 if(rh_true>100)rh_true=100; //湿度最大修正 if(rh_true<0.1)rh_true=0.1; //湿度最小修正 *p_temperature=t_C; //返回温度结果 *p_humidity=rh_true; //返回湿度结果 //从相对温度和湿度计算露点 /*float calc_dewpoint(float h,float t) { } float logEx,dew_point; logEx=0.66077+7.5*t/(237.3+t)+(log10(h)-2); dew_point = (logEx - 0.66077)*237.3/(0.66077+7.5-logEx); return dew_point; */ #include //11.0592MHz晶振频率 - 38 - } EA=1; ES=1; TMOD=0x20; SCON=0x40; TH1=0xFD; TL1=0xFD; //PCON=0x00; //倍率加倍,屏蔽此句,波特率为9600 TR1=1; void UART_SendChar(char dat) { TI=0; SBUF=dat; //发送数据 while(TI==0); //检查发送完成中断标志如果未完成就等等否 则复位发送标志位以便下个数据可以发送 } void UART_SendString(char* dat) { } //主函数(main.c): #include unsigned char i=0; while(dat[i]) { UART_SendChar(dat[i++]); delay(30); } - 39 - typedef union { } value; //延时函数 //定义共用同类型 unsigned int i; float f; void delay(int z) { } void main() { //z为毫秒数 int x,y; for(x=z;x>0;x--) for(y=125;y>0;y--); unsigned int temp,humi; value humi_val,temp_val; //定义两个共同体,一个用于湿 度,一个用于温度 // float dew_point; //用于记录露点值 //用于检验是否出现错误 //CRC unsigned char error; unsigned char checksum; uchar wendu[6]; uchar shidu[6]; UART_init(); LCD_Initial(); GotoXY(0,0); //用于记录温度 //用于记录湿度 //初始化液晶 //选择温度显示位置 //5格空格 Print(\"WenDu: %C\"); GotoXY(0,1); //选择湿度显示位置 //5格空格 Print(\"ShiDu: %RH\"); - 40 - s_connectionreset(); while(1) { error=0; //启动连接复位 //初始化error=0,即没有错误 error+=s_measure((unsigned char*)&temp_val.i,&checksum,TEMP); //温度测量 error+=s_measure((unsigned char*)&humi_val.i,&checksum,HUMI); //湿度测量 if(error!=0) s_connectionreset(); //// 如果发生错误,系统复位 else { humi_val.f=(float)humi_val.i; // 湿度转换为浮点数 转换为浮点数 calc_sth10(&humi_val.f,&temp_val.f); //修正temp_val.f=(float)temp_val.i; //温度 相对湿度及温度 // dew_point temp=temp_val.f*10; dew_point=calc_dewpoint(humi_val.f,temp_val.f); //计算e humi=humi_val.f*10; GotoXY(7,0); //设置温度显示位置 //温度百位 //温度十位 //温度个位 wendu[0]=temp/1000+'0'; wendu[1]=temp%1000/100+'0'; wendu[2]=temp%100/10+'0'; wendu[3]=0x2E; //小数点 //温度小数点后第一位 wendu[4]=temp%10+'0'; - 41 - 置 Print(wendu); //输出温度 //设置湿度显示位 GotoXY(7,1); shidu[0]=humi/1000+'0'; //湿度百位 shidu[1]=humi%1000/100+'0'; shidu[2]=humi%100/10+'0'; //湿度十位 //湿度个位 shidu[3]=0x2E; //小数点 //湿度小数点后第一位 shidu[4]=humi%10+'0'; } Print(shidu); //输出湿度 wendu[5]=shidu[5]=0; UART_SendString(\"Temperature: \"); UART_SendString(wendu); UART_SendString(\" %C \\x0D\\x0A\"); UART_SendString(\"Humidity: \"); UART_SendString(shidu); UART_SendString(\" %RH \\x0D\\x0A\\x0D\\x0A\"); delay(1000); //等待足够长的 时间,以现行下一次转换 } } - 42 - 因篇幅问题不能全部显示,请点此查看更多更全内容