您好,欢迎来到五一七教育网。
搜索
您的当前位置:首页基于52单片机温湿度传感器课程设计报告(含代码)

基于52单片机温湿度传感器课程设计报告(含代码)

来源:五一七教育网


基于52单片机的温湿 度检测仪的设计

摘要

利用Atmel52系列单片机和数字温湿度传感器AM2301设计并制作一个简单的温湿度检测仪。以单片机为核心,外围电路包括电源、时钟芯片、128LCD、Max232芯片、AM2301传感器以及蜂鸣器报警电路等。其中AM2301传感器是含有已校准数字信号输出的温湿度复合传感器,它包括一个电阻式感湿元件和一个NTC测温元件。LCD显示包括万年历、温湿度以及报警设置,同时通过内部中断方式把温湿度的实时值通过VB编写的上位机程序接收并显示。

一、 设计功能

(1) LCD分两个界面显示:主界面和设置报警界面; (2) 主界面显示万年历和温湿度实时值;

3) 设置报警界面显示温湿度上下限及开/关报警;

4) 当温湿度低于设置的下限或高于设置的上限并且开报警后,蜂

((

鸣器和led灯配合报警;

(5) 有按键设置功能,以及关报警和回到主界面显示功能; (6) 能通过Max芯片和计算机通信,把温湿度数据显示在上位机界

面上,实现远程监控。

二、 设计所需元件清单 (1)9V电源 (2)杜邦线若干 (3)128LCD1块 (4)80X52单片机1片 (5)排阻1排,电阻若干 (6)AM2301传感器1个

(7)32768Hz晶振1个,12MHz晶振1个 (8)蜂鸣器1个

(9)LM2940稳压元件1个 (10)DS1302时钟芯片1片 (11)船型开关1个,触点开关若干 (12)30pF电容若干,22uF电容若干 (13)LED灯2个,三极管,纽扣电池 三、具体设计

根据所要实现的功能,将系统模块化设计,总体模块结构图如下图所示:

以下就分别就各模块功能实现进行设计。

1. 复位电路

这部分是单片机一般都需要的,当运行出错或者死机时,利用复位按键能重新启动系统。

RST

2. 时钟电路

如上图所示。其中时钟芯片DS1302的各引脚功能如下:

Vcc1:主电源;Vcc2:备份电源。当Vcc2>Vcc1+0.2V时,由Vcc2 向DS1302供电,当Vcc2< Vcc1时,由Vcc1向DS1302供电。 SCLK:串行时钟,输入,控制数据的输入与输出; I/O:三线接口时的双向数据线;

RST为复位引脚,在读、写数据期间,必须为高, X1 X2为32867Hz晶振管脚,为芯片提供时钟脉冲。

3. 报警电路

各I/O口在上电时为高电平,LED灯和蜂鸣器处于熄灭和不响状态。其中LED灯通过一个1K的电阻限流,防止点亮时电流过大被烧

坏。蜂鸣器要用NPN型三极管驱动,当P2.5口输出高电平时,Q1饱和导通,蜂鸣器获得工作电流发出响声。

4. 键盘扫描电路

这里用了5个按键。其中按键1是调时按键,根据按的次数依次进入年、月、日、时、分、秒、星期调整,再按一次则退出。按键2和3分别是加操作和减操作。按键4是设置温湿度上下限值及报警开关;按键5是关报警。

5. 128LCD显示电路

ST7920系列128是带中文字库的液晶显示器,它可以显示4行,每行16个字节,各行的地址依次为0x80~0x87、0x90~0x97、0x88~0x8F 0x98~0x9F。

注:RB0~RB7(为数据口)依次接P1各口,变阻器R2下端接地。 5.1接口说明:

VSS为电源地;VDD为电源正端;V0为LCD驱动电压输入端; RS:并行的指令/数据选择信号,串行的片选信号; RW:并行的读写选择信号,串行的数据口; E:并行的使能信号,串行的同步时钟; PSB:并/串行接口选择,高电平时为并行; NC:空脚;

RST:复位信号,低电平有效; BLA:背光源正极; BLK:背光源负极。

5.2、128读写时序图如下:

读写操作时序

数据与命令时序 5.3、基本操作时序

(1)读状态:输入:RS=L,RW=H,E=H 输出:D0~D7=状态字 (2)写指令:输入:RS=L,RW=L, D0~D7=指令码,E=高脉冲 输出:无

(3)读数据:输入:RS=H,RW=H,E=H 输出:D0~D7=数据

(4)写数据:输入:RS=H,RW=L, D0~D7=数据,E=高脉冲 输出:无

5.4、初始化过程(复位过程)指令: (1)延时15毫秒

(2)写指令38H;显示模式设置 (3)写指令08H;显示关闭 (4)写指令01H;显示清屏 (5)写指令06H;显示光标移动设置 (6)写指令0CH;显示开及光标设置

6. 与PC机通信模块

从上述电路可知,单片机要与计算机通信,必须通过MAX232(或其他)芯片。这是因为计算机串口上的电平执行的是RS-232标准,它定义的高低电平和单片机的TTL逻辑电平不兼容。而MAX232芯片加上几个电解电容,能完成电压的加倍和反相,实现TTL电平和RS-232电平的转换。单片机的串行口TXD与MAX232的一组电平转换器的TTL输入端(管脚12)相连,经过MAX232转换后,RS-232标准输出端(管脚14)输出的信号进入计算机串口的RXD。同样计算机串口的TXD与MAX232的RS-232标准输入端(管脚13)相连,经过电平转换后,由TTL输出端(管脚11)输出到单片机的RXD上。

7. AM2301温湿度检测电路

上图中DHT11和AM2301是一个系列的,他们的引脚和功能一样。

7.1 AM2301温湿度传感器简介

DHT11的供电电压为3-5.5V。传感器上电后,要等待1s 以越过不稳定状态在此期间无需发送任何指令。电源引脚(VDD,GND)之间可增加一个100nF 的电容,用以去耦滤波。DATA 用于微处理器与DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数部分用于以后扩展,现读出为零.操作流程如下:一次完整的数据传输40bit,高位先出。数据格式:8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,用户可选择读取部分数据.从模式下,DHT11接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集.采集数据后转换到低速模式。

1、总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us低电平响应信号.主机发送开始信号结束后,延时等待20-40us后, 读取DHT11的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可, 总线由上拉电阻拉高。

2、总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉高80us,准备发送数据,每一bit数据都以50us低电平时隙开始,高电平的长短定了数据位是0还是1.格式见下面图示.如果读取响应信号为高电平,则DHT11没有响应,请检查线路是否连接正常.当最后一bit数据传送完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态。

四、 各模块流程图

1、 温度模块控制流程图:

开始初始化写字节0xCC启动温湿度转换延时初始化写字节0xCC2、 湿度模块控制流程图

读取温湿度寄存器读温湿度的两个字节温度的数值转换为字符温湿度传送结束

开始初始化P1.0是否为低电平是等待P1.0变为高电平P1.0变为高电平否等待P1.0变为低电平U8checkdata_temp =U8temp?读取温湿度的字节否读一个字节得U8checkdata_temp 信号是传送温湿度温湿度相加得U8temp信号结束

3、 显示模块控制流程图

4、 报警模块流程图

5、 温湿度报警设置流程图

6、万年历设置流程图

控制键有效,进入年调整程序控制键有效,进入月调整程序等待按键程序等待按键程序加/减键有效加/减键有效年加减1月加减1控制键有效,进入日调整程序控制键有效,进入星期调整程序等待按键程序等待按键程序加/减键有效加/减键有效日加减1星期加减1控制键有效,进入时调整程序控制键有效,进入分调整程序控制键有效,进入秒调整程序等待按键程序等待按键程序等待按键程序加/减键有效加/减键有效时加减1分加减1加/减键有效秒加减1控制键有效,跳出时间调整程序,进入主循环程序

7、 与PC通信模块流程图

五、 设计过程问题解决

本次设计过程很费周折,由于proteus里面缺少一些必要的元件如20引脚128液晶显示模块和AM2301温湿传感器,故实验过程中是先设计好硬件电路,焊好电路以后才进行调试的,其间的艰难可想而知。也因为这样,硬件电路的错误比较多,中间一直在修改硬件电路,造成电路板修修补补不美观。

实验过程中遇到的困难很多 ,尤其是实现界面切换和返回主界面的过程,要保持时钟仍在运行,同时光标也要随着界面一起移动。否则就会显示出错。此外开关报警的设置如何能够保持,这就要做到返回主界面以后要保存设置量,当报警时按下了关报警,要刷新设置界面。而在本次设计过程中,我们调用了两次显示,一次写显示格式,一次刷新,只要有更改就刷新,对于那些不变的汉字我们不刷新,这样也使得显示得到简化。

此外,由于使用到单片机与计算机通信知识,通过查阅相关书籍,用VB编写了一个上位机显示界面,将128上显示的温湿度数值通过串口控件显示。

下面将分步骤将实现过程中的问题和解决方案作说明:

1. 刚开始烧了程序以后,发现LCD什么都不显示,后来发现是因为没有开背光,因为没开背光显示不明显,如果角度不对会发现什么都没显示。而背光要通过可调电阻来调,在128的BLA背光正极接一个可调电阻,电阻的两端是接地和电源(之间还有一个拨码开关)。当打开开关时,背光关掉,可以省电;合上开关,调

节电阻可以使128显示亮度变化。

2. 能够显示以后,发现显示界面一直在刷新,显示不稳定。原因是每秒随着秒刷新初始化界面一次,解决的方案是不重新调用显示,而是只给显示秒的位置刷新,其他时间随秒变化。温湿度值则是有了变化就刷新。

3. 由于编写程序时,没有考虑到串口通信中传回PC的数据的十六进制与显示字符之间的数据处理关系,导致在串口助手软件中只显示了传回的最后一个十六进制数所对应的ASCⅡ的字符,找到问题的解决关键所在后,经过数的分位与字符显示后,成功的显示了传回的温度、湿度的数据,让我们距离成功只差一小步了。接下来的任务就是显示在128液晶上,根据之前单独在其上显示过液晶万年历的基础,知道只要将dht11检测的数据进行相应处理后并且与液晶万年历的显示集成一起送显示就行了。理论虽简单,但实际在下载到芯片中检测现象时,我们发现分别单独显示两者的数据没有问题,但集成在一块显示不久就会花屏的现象,问题出在刷新汉字时,指针光标的位置修改错误所导致的。之后经过重新写回指针后就达到了较为满意的效果。在报警程序的设置上,主要解决蜂鸣器报警间隔和LED灯闪烁的时间匹配问题,让两者现象统一。

4. 单片机与计算机通信。上位机界面设计,利用VB编程,用MSComm控件能够实现单片机传送数据到计算机并显示。

Private Sub MSComm1_OnComm() Dim rec As String ;定义接收字符串

Select Case MSComm1.CommEvent ;串口事件选择 Case comeEvReceive ;串口事件为接收

rec = MSComm1.Input ;从接收缓冲区中读取数据 Text1.Text = rec ;将接收到的字符串写入文本框 MSComm1.InBufferCount = 0 ;设置接收缓冲区中等待计算机接受的字符数为0

End Select End Sub

Private Sub form_load()

MSComm1.Settings = \"9600,N,8,1\" ;波特率,奇偶校验,发送位数,停止位

MSComm1.CommPort = 5 ;串口号 If MSComm1.PortOpen = True Then MSComm1.PortOpen = False

MSComm1.RThreshold = 8 ;接收缓冲区字符为8时,串口控件设置串口事件为接收,并产生OnComm事件

MSComm1.SThreshold = 2 ;发送缓冲区中字符小于2时,串口控件设置串口事件为发送,并产生OnComm事件

MSComm1.InputLen = 0 ;返回一次从接收缓冲区读取所有字节

MSComm1.InputMode = comInputModeText ;接收模式为文本

If MSComm1.PortOpen = False Then MSComm1.PortOpen = True

MSComm1.InBufferCount = 0 Me.Caption = \"温湿度显示\" End Sub

Private Sub Form_Resize() ;窗体背景图片设置 Image1.Top = 0 Image1.Left = 0 Image1.Stretch = True

Image1.Height = Me.ScaleHeight Image1.Width = Me.ScaleWidth End Sub

Private Sub mnuQuit_Click() End End Sub

六、 设计总结

本次设计是小组三人共同努力的成果,大家齐心协力克服了上述种种困难,才把实物做出来。通过这次设计,我们学习到了如何把传感器联系单片机知识做成一个简单的检测系统,如何完成简单

的通信任务,如何编写高效率的C代码。当然我们的不足也有很多,比如硬件设计电路考虑不全面,造成后来不得不修改一些连线和元件使得电路板不够美观;还有程序不够模块化,有不少冗余,移植性和兼容性也不好,今后要更加注重这些方面的改进。

附录代码:

/*****基于单片机的温湿度检测系统******/ #include

#define uchar unsigned char #define uint unsigned int /***端口定义***/

sbit LCD_RS=P3^5; //寄存器选择输入 sbit LCD_RW=P3^6; //液晶读/写控制 sbit LCD_EN=P3^4; //液晶使能控制 sbit LCD_PSB=P3^7; //串/并方式控制 sbit s5=P0^3; //关报警 sbit s4=P0^4; //设置温湿度报警值及开关报警 sbit s3=P0^5; //调时开/关 sbit s2=P0^6; //加操作 sbit s1=P0^7; //减操作 sbit led1=P2^0; //温度报警 sbit led2=P2^1; //湿度报警 sbit buzzer=P2^5; //蜂鸣器 sbit AM2301=P2^6; //P2.6口为通讯口连接DHT11 typedef unsigned char U8; typedef unsigned int U16;

char sec,min,hour,week,day=1,month=1,year; bit flag,flag2,flag3=0,flag4=0,flag5=0,flag6=0; uchar a;

uchar s1num,s4num;

uchar code dis1[]={\"2011年12月02日\uchar code dis2[]={\"00时00分00秒\uchar code dis3[]={\"温度: 25.0 日\uchar code dis4[]={\"湿度: 40.0\

uchar code dis5[]={\"温度上限:\温湿度设置界面 uchar code dis6[]={\"温度下限:\uchar code dis7[]={\"湿度上限:\uchar code dis8[]={\"湿度下限:\uchar code disx[]={0xc8,0xd5,0xd2,0xbb,0xb6,0xfe,0xc8,0xfd,0xcb,0xc4,0xce,0xe5,0xc1,0xf9};//\"

日\一\二\三\四\五\六\"(两个字节为一个汉字) //----------------定义区--------------------// U8 Temp,RH1; U8 U8FLAG;

U8 U8count,U8temp;

U8 data tab[8]={0x00,0x00,0x2e,0x00,0x00,0x00,0x2e,0x00};//存储温湿度数据

U8 U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;//温湿度的高低位及校验位 U8

U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;

U8 temp_H=30,temp_L=0,RH_H=50,RH_L=10; U8 U8comdata;

U8 outdata[8]; //定义发送的字节数 U8 str[8]={“”}; U8 count;

U16 U16temp1,U16temp2; /***延时1ms子函数***/ void delay(uint z) { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); }

/***延时子函数***/ void Delay2(U16 j) { U8 i;

for(;j>0;j--) for(i=0;i<27;i++); }

/***延时10us子函数***/ void Delay_10us(void) { U8 i; i--; i--; i--; i--; i--; i--; }

/***发送字符串子函数***/ void SendData(U8*a)

{

outdata[0]=a[0]; outdata[1]=a[1]; outdata[2]=a[2]; outdata[3]=a[3]; outdata[4]=a[4]; outdata[5]=a[5]; outdata[6]=a[6]; outdata[7]=a[7]; count=0;

SBUF=outdata[0]; }

/***写指令子函数***/

/*RS=0,RW=0,E=0,D0-D7=指令码*/ void write_(uchar ) { LCD_RS=0; LCD_RW=0; LCD_EN=0; P1=; delay(5); LCD_EN=1; delay(5); LCD_EN=0; }

/***写数据子函数***/

/*RS=1,RW=0,E=0,D0-D7=数据*/ void write_dat(uchar dat) { LCD_RS=1; LCD_RW=0; LCD_EN=0; P1=dat; delay(5); LCD_EN=1; delay(5); LCD_EN=0; }

/***设定显示位置***/

void lcd_pos(uchar X,uchar Y) { uchar pos; if(X==0) X=0x80;

else if(X==1) X=0x90; else if(X==2) X=0x88; else if(X==3) X=0x98; pos=X+Y; write_(pos); }

/***LCD初始化设定***/ void init() { LCD_PSB=1; //并口方式 write_(0x30); //基本指令操作 delay(5); write_(0x0c); //显示开,关光标 delay(5); write_(0x01); //清除LCD的显示内容 delay(5); TMOD=0x21; TH0=0x4c; TL0=0x00; ET0=1; EA=1; TR0=1; TH1=253;//初始化串口 TL1=253; TR1=1; SCON=0x50; ES=1; EA=1; TI=0; RI=0;

SendData(str); Delay2(1); }

/***写年月日子函数***/

void write_ymd(uchar add,uchar dat) { uchar shi,ge; shi=dat/10; ge=dat%10; write_(0x80+add); write_dat(0x30+shi);

write_dat(0x30+ge); }

/***写时分秒子函数***/

void write_hms(uchar add,uchar dat) { uchar shi,ge; shi=dat/10; ge=dat%10; write_(0x90+add); write_dat(0x30+shi); write_dat(0x30+ge); }

/******温湿度上下限设置更新***********/ void write_lim1(uchar add,uchar dat) {

uchar shi,ge; shi=dat/10; ge=dat%10; write_(0x80+add); write_dat(0x30+shi); write_dat(0x30+ge); }

void write_lim2(uchar add,uchar dat) {

uchar shi,ge; shi=dat/10; ge=dat%10; write_(0x90+add); write_dat(0x30+shi); write_dat(0x30+ge); }

void write_lim3(uchar add,uchar dat) {

uchar shi,ge; shi=dat/10; ge=dat%10; write_(0x88+add); write_dat(0x30+shi); write_dat(0x30+ge); }

void write_lim4(uchar add,uchar dat) {

uchar shi,ge; shi=dat/10;

ge=dat%10; write_(0x98+add); write_dat(0x30+shi); write_dat(0x30+ge); }

/*温度显示子函数*/

void write_tem(uchar add) { write_(0x88+add); write_dat(tab[4]); write_dat(tab[5]); write_dat(tab[6]); write_dat(tab[7]); }

/*湿度显示子函数*/

void write_hum(uchar add) { write_(0x98+add); write_dat(tab[0]); write_dat(tab[1]); write_dat(tab[2]); write_dat(tab[3]); }

void COM(void) { U8 i; for(i=0;i<8;i++) { U8FLAG=2; while((!AM2301)&&U8FLAG++); Delay_10us(); Delay_10us(); Delay_10us(); U8temp=0; if(AM2301)U8temp=1; U8FLAG=2; while((AM2301)&&U8FLAG++); //超时则跳出for循环 if(U8FLAG==1)break; //判断数据位是0还是1 // 如果高电平高过预定0高电平值则数据位为 1

U8comdata<<=1; U8comdata|=U8temp; } }

/***温湿度读取子函数***/ void RH(void) { //主机拉低18ms AM2301=0; Delay2(180); AM2301=1; //总线由上拉电阻拉高 主机延时40us Delay_10us(); Delay_10us(); Delay_10us(); Delay_10us(); //主机设为输入 判断从机响应信号 AM2301=1; //判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行 if(!AM2301) //T ! { U8FLAG=2; //判断从机是否发出 80us 的低电平响应信号是否结束 while((!AM2301)&&U8FLAG++); U8FLAG=2; //判断从机是否发出 80us 的高电平,如发出则进入数据接收状态 while((AM2301)&&U8FLAG++); //数据接收状态 COM(); U8RH_data_H_temp=U8comdata; COM(); U8RH_data_L_temp=U8comdata; COM(); U8T_data_H_temp=U8comdata; COM(); U8T_data_L_temp=U8comdata; COM(); U8checkdata_temp=U8comdata; AM2301=1; //数据校验 U8temp=(U8T_data_H_temp+U8T_data_L_temp+U8RH_data_H_temp+U8RH_data_L_temp);

if(U8temp==U8checkdata_temp) if(1) { U8RH_data_H = U8RH_data_H_temp;//湿度 U8RH_data_L = U8RH_data_L_temp; U16temp1 = U8RH_data_H; U16temp1 <<= 8; U16temp1 |= U8RH_data_L;//获得完整的湿度 tab[0]=U16temp1/100+0x30; //湿度百位 tab[1]=U16temp1%100/10+0x30;//湿度十位 tab[3]=U16temp1%10+0x30; //湿度个位 U8T_data_H = U8T_data_H_temp;//温度 U8T_data_L = U8T_data_L_temp; U16temp2 = U8T_data_H; U16temp2<<=8; U16temp2 |= U8T_data_L;//获得完整的温度 tab[4]=U16temp2/100+0x30;//温度百位 tab[5]=U16temp2%100/10+0x30;//温度十位 tab[7]=U16temp2%10+0x30;//温度个位 U8checkdata=U8checkdata_temp;//校验位 } } }

/*******主界面显示*********/ void display1() {

uchar i; init();

/***从第一行第一个字符的位置开始显示***/ lcd_pos(0,0); i=0; while(dis1[i]!='\\0') { write_dat(dis1[i]); i++; }

/***从第二行第一个字符的位置开始显示***/ lcd_pos(1,0); i=0; while(dis2[i]!='\\0') {

write_dat(dis2[i]); i++; }

/***从第三行第一个字符的位置开始显示***/ lcd_pos(2,0); i=0; while(dis3[i]!='\\0') { write_dat(dis3[i]); i++; }

/***从第四行第一个字符的位置开始显示***/ lcd_pos(3,0); i=0; while(dis4[i]!='\\0') { write_dat(dis4[i]); i++; } }

/*****温湿度上下限及报警开关设置界面***********/ void display2() {

uchar i; init();

/***从第一行第一个字符的位置开始显示***/ lcd_pos(0,0); i=0; while(dis5[i]!='\\0') { write_dat(dis5[i]); i++; } write_lim1(5,temp_H); write_dat(0x2e); write_dat(0x30); if(flag3) { write_(0x80+7); write_dat(0xbf); write_dat(0xaa); } else

{ write_(0x80+7); write_dat(0xb9); write_dat(0xd8); }

/***从第二行第一个字符的位置开始显示***/ lcd_pos(1,0); i=0; while(dis6[i]!='\\0') { write_dat(dis6[i]); i++; } write_lim2(5,temp_L); write_dat(0x2e); write_dat(0x30); if(flag4) { write_(0x90+7); write_dat(0xbf); write_dat(0xaa); } else { write_(0x90+7); write_dat(0xb9); write_dat(0xd8); }

/***从第三行第一个字符的位置开始显示***/ lcd_pos(2,0); i=0; while(dis7[i]!='\\0') { write_dat(dis7[i]); i++; } write_lim3(5,RH_H); write_dat(0x2e); write_dat(0x30); if(flag5) { write_(0x88+7); write_dat(0xbf); write_dat(0xaa);

} else { write_(0x88+7); write_dat(0xb9); write_dat(0xd8); }

/***从第四行第一个字符的位置开始显示***/ lcd_pos(3,0); i=0; while(dis8[i]!='\\0') { write_dat(dis8[i]); i++; } write_lim4(5,RH_L); write_dat(0x2e); write_dat(0x30); if(flag6) { write_(0x98+7); write_dat(0xbf); write_dat(0xaa); } else { write_(0x98+7); write_dat(0xb9); write_dat(0xd8); } }

/*****调时按键扫描*******/ void keyscan1() { if(s1==0) { delay(5);//延时5ms去抖动! if(s1==0) { while(!s1); s1num++;

if(s1num==1) { TR0=0; write_(0x80+1); write_(0x0f); }

if(s1num==2) { write_(0x80+3); }

if(s1num==3) { //TR0=0; 上一次已经停了。 write_(0x80+5); //write_(0x0f); }

if(s1num==4) { //TR0=0; 上一次已经停了。 write_(0x90+0); //write_(0x0f); }

if(s1num==5) { //TR0=0; 上一次已经停了。 write_(0x90+2); //write_(0x0f);上一次光标已闪烁 }

if(s1num==6) { //TR0=0; 上一次已经停了。 write_(0x90+4); //write_(0x0f);上一次光标已闪烁 }

if(s1num==7) { write_(0x88+7); }

if(s1num==8) { s1num=0; TR0=1; write_(0x0c); }

} }

if(s1num!=0) { /***按键计数加***/ if(s2==0) { delay(5); if(s2==0) { while(!s2);//消抖,否则就会一下加很多 /***调节修改显示的位置***/ if(s1num==1) { year++; if(year==99) year=0; //刷新年! write_ymd(1,year); write_(0x80+1); } if(s1num==2) { month++; if(month==13) month=1; //刷新月! write_ymd(3,month); write_(0x80+3); } if(s1num==3) { day++; if(day==32) day=1; //刷新日! write_ymd(5,day); write_(0x80+5); } if(s1num==4) { hour++; if(hour==24) hour=0;

//刷新时! write_hms(0,hour); write_(0x90+0); } if(s1num==5) { min++; if(min==60) min=0; //刷新分! write_hms(2,min); write_(0x90+2); } if(s1num==6) { sec++; if(sec==60) sec=0; //刷新秒! write_hms(4,sec); write_(0x90+4); } if(s1num==7) { uchar i; week++; if(week==7) week=0; //刷新星期! i=2*week; while(i<2*week+2) { write_dat(disx[i]); i++; } write_(0x88+7); } } }

/***按键计数减***/ if(s3==0) { delay(5); if(s3==0)

{

while(!s3);//消抖,否则就会一下加很多 /***调节修改显示的位置***/ if(s1num==1) { year--; if(year==-1) year=99; write_ymd(1,year); write_(0x80+1); }

if(s1num==2) { month--; if(month==0) month=12; write_ymd(3,month); write_(0x80+3); }

if(s1num==3) { day--; if(day==0) day=31; write_ymd(5,day); write_(0x80+5); }

if(s1num==4) { hour--; if(hour==-1) hour=23; write_hms(0,hour); write_(0x90+0); }

if(s1num==5) { min--; if(min==-1) min=59; write_hms(2,min); write_(0x90+2); }

if(s1num==6)

{ sec--; if(sec==-1) sec=59; write_hms(4,sec); write_(0x90+4); } if(s1num==7) { uchar i; week--; if(week==-1) week=6; i=2*week; while(i<2*week+2) { write_dat(disx[i]); i++; } write_(0x88+7); } } } } }

/*****温湿度上下限设置按键扫描**********/ void keyscan2() { if(s4==0) { delay(5); if(s4==0) { while(!s4); s4num++; if(s4num==1) { TR0=0; display2(); write_(0x80+5); write_(0x0f); } if(s4num==2)

{ write_(0x80+7); } if(s4num==3) { write_(0x90+5); } if(s4num==4) { write_(0x90+7); } if(s4num==5) { write_(0x88+5); } if(s4num==6) { write_(0x88+7); } if(s4num==7) { write_(0x98+5); } if(s4num==8) { write_(0x98+7); } if(s4num==9) { s4num=0; TR0=1; display1(); //write_(0x0c); } } }

//按键s4次数 if(s4num!=0) { /***按键计数加***/ if(s2==0) { delay(10);

if(s2==0) { while(!s2);//消抖,否则就会一下加很多 /***调节修改显示的位置***/ if(s4num==1) { temp_H++; if(temp_H==80) temp_H=30; //刷新温度上限 write_lim1(5,temp_H); write_(0x80+5); } if(s4num==2) { flag3=~flag3; if(flag3) { write_(0x80+7); write_dat(0xbf); write_dat(0xaa); write_(0x80+7); } else { write_(0x80+7); write_dat(0xb9); write_dat(0xd8); write_(0x80+7); } } if(s4num==3) { temp_L++; if(temp_L==29) temp_L=0; //刷新温度下限 write_lim2(5,temp_L); write_(0x90+5); } if(s4num==4) { flag4=~flag4; if(flag4)

{ write_(0x90+7); write_dat(0xbf); write_dat(0xaa); write_(0x90+7); } else { write_(0x90+7); write_dat(0xb9); write_dat(0xd8); write_(0x90+7); } } if(s4num==5) { RH_H++; if(RH_H==99) RH_H=50; //刷新湿度上限 write_lim3(5,RH_H); write_(0x88+5); } if(s4num==6) { flag5=~flag5; if(flag5) { write_(0x88+7); write_dat(0xbf); write_dat(0xaa); write_(0x88+7); } else { write_(0x88+7); write_dat(0xb9); write_dat(0xd8); write_(0x88+7); } }

if(s4num==7) { RH_L++;

if(RH_L==49) RH_L=10; //刷新湿度上限 write_lim4(5,RH_L); write_(0x98+5); } if(s4num==8) { flag6=~flag6; if(flag6) { write_(0x98+7); write_dat(0xbf); write_dat(0xaa); write_(0x98+7); } else { write_(0x98+7); write_dat(0xb9); write_dat(0xd8); write_(0x98+7); } } } }

if(s4num!=0) { /***按键计数减***/ if(s3==0) { delay(10); if(s3==0) { while(!s3);//消抖,否则就会一下加很多 /***调节修改显示的位置***/ if(s4num==1) { temp_H--; if(temp_H==30) temp_H=80; //刷新温度上限 write_lim1(5,temp_H);

write_(0x80+5); }

if(s4num==2) {

flag3=~flag3; if(flag3) {

write_(0x80+7); write_dat(0xbf); write_dat(0xaa); write_(0x80+7); } else { write_(0x80+7); write_dat(0xb9); write_dat(0xd8); write_(0x80+7); } }

if(s4num==3) { temp_L--; if(temp_L==0) temp_L=29; //刷新温度下限 write_lim2(5,temp_L); write_(0x90+5); }

if(s4num==4) {

flag4=~flag4; if(flag4) {

write_(0x90+7); write_dat(0xbf); write_dat(0xaa); write_(0x90+7); } else { write_(0x90+7); write_dat(0xb9); write_dat(0xd8);

write_(0x90+7); } } if(s4num==5) { RH_H--; if(RH_H==50) RH_H=99; //刷新湿度上限 write_lim3(5,RH_H); write_(0x88+5); } if(s4num==6) { flag5=~flag5; if(flag5) { write_(0x88+7); write_dat(0xbf); write_dat(0xaa); write_(0x88+7); } else { write_(0x88+7); write_dat(0xb9); write_dat(0xd8); write_(0x88+7); } }

if(s4num==7) { RH_L--; if(RH_L==10) RH_L=49; //刷新湿度上限 write_lim4(5,RH_L); write_(0x98+5); } if(s4num==8) { flag6=~flag6;

if(flag6) { write_(0x98+7); write_dat(0xbf); write_dat(0xaa); write_(0x98+7); } else { write_(0x98+7); write_dat(0xb9); write_dat(0xd8); write_(0x98+7); } } } } } } }

/*****关报警*********/ void shut() {

if(s5==0) {

delay(5); if(s5==0) { while(!s5); led1=1;led2=1;buzzer=1; flag3=0;flag4=0;flag5=0;flag6=0; } } }

/*******主函数**********/ void main() { display1(); //主界面显示 while(1) { keyscan1(); //调时按键扫描 keyscan2(); //调温湿度报警按键扫描 RH(); //温湿度数据获取

if(s1num==0&&flag2==1&&s4num==0) { uchar i; i=0;

while(i<8) {

str[i]=tab[i]; i++; }

SendData(str); //通过串口发送数据

Delay2(20000); //读取模块周期应不小于2s write_tem(3); //显示温度 write_hum(3); //显示湿度 Temp=(tab[4]-0x30)*10+tab[5]-0x30; RH1=(tab[0]-0x30)*10+tab[1]-0x30; if((Temp>=temp_H&&flag3==1)||(Temp<=temp_L&&flag4==1)) 报警 { led1=0;buzzer=0;delay(200);led1=1;buzzer=1; } if((RH1>RH_H&&flag5==1)||(RH1/***万年历中断***/

void timer_0() interrupt 1 using 1 { uchar i; flag2=0; TH0=0x4c; TL0=0x00; a++; if(a==20) { a=0; sec++; flag2=1; if(sec==60)

//温度

{ sec=0;

min++;

if(min==60) 判断条件

{ min=0; hour++; if(hour==24) { hour=0; day++; week++; if(week==7) week=0; flag=(((year%4==0)&&(year%100!=0))||(year%400==0));//闰年的 /***闰年二月29天***/

if(day==30&&month==2&&flag==1) { day=1; month++; if(s4num==0) { write_ymd(3,month); } }

/***其余二月28天***/

if(day==29&&month==2&&flag==0) { day=1; month++; if(s4num==0) { write_ymd(3,month); } }

/***30天的月份***/

if((month==4||month==6||month==9||month==11)&&day==31) { day=1; month++; if(s4num==0) {

write_ymd(3,month);

} } /***31天的月份***/ if((month==1||month==3||month==5||month==7||month==8||month==10||month==12)&&day==32) { day=1; month++; if(month==13) { month=1; year++; if(s4num==0) { write_ymd(1,year); } } if(s4num==0) { write_ymd(3,month); } } if(s4num!=0) { write_ymd(5,day); } write_(0x88+6); //写入修改星期数 i=2*week; while(i<2*week+2) { if(s4num==0) { write_dat(disx[i]); i++; } } write_(0x88+6); } if(s4num==0) {

write_hms(0,hour); } } if(s4num==0) { write_hms(2,min); } } if(s4num==0) { write_hms(4,sec); } } }

/***串口发送中断子函数****/

void RSINTR() interrupt 4 using 2 {

if(TI==1) //发送中断 {

TI=0; //关发送中断,允许发送 if(count!=8) //发送完8位数据 {

SBUF=outdata[count]; count++; } } }

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- 517ttc.cn 版权所有 赣ICP备2024042791号-8

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务