温度控制系统的设计方案理解

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

温度控制系统的设计
第一章绪论
1.1温度控制系统的设计背景
温度是一个和人们生活环境有密切关系的物理量,也是一个人们在科学实验和生产生活中经常需要加以监测和控制的重要物理量。

温度控制技术是一种比较重要的工业技术,不仅应用在化工、医疗、航空、航天等高科技领域,还应用在人们的日常生活中。

在现代化电器装置中,许多设备也装有电风扇用于散热,但是在设备长期的运行中,若电风扇损坏的话,对设备的运行有潜在的威胁。

为了保障设备的可靠运行,需要人们专门设计一个具有超温或低温报警功能温控系统,当设备的温度超过或低于某一限制时发出报警声,并能实现温度的自动调节。

1.2温度控制系统发展状况
现在工业上用到的温度控制系统一般是干式变压器温度控制系统,经历了盘式温度表、毛细管式温控器、PTC(正温度系数)热敏电阻温控装置、铂热电阻测温装置的发展历程。

随着电力工业的发展,温度控制系统的设计水平也相应的有所提高和完善。

前三种温控系统逐渐被淘汰,铂热电阻温控系统则得到了长足发展。

随着干式变压器应用领域的不断扩展,温度控制系统的功能也得到不断的完善——A、B、C三相巡回显示;最大值显示;直接启停风机;超温、故障报警;光电耦合,冗余保护系统;自修正子程序等。

第二章温度控制系统设计要求
2.1系统设计要求
1.能够采集温度,且精度达到0.1℃。

2.采集到的温度能够在液晶屏上显示出来,并且温度低于20℃时,系统能够驱动加热装置加热,温度高于40℃,系统能够驱动电风扇运转,且能够发出闹钟报警。

3.在液晶屏上显示万年历。

第三章温度控
制系统方案论证
3.1温控系统的总体方案
本系统由51系列单片机AT89S52、按键、时钟、液晶显示和外围降温、加热电路等部分构成。

对温度进行实时采集并通过程序设定最高温度、最低温度。

采集到的实时温度通过串口向单片机进行传输,最后将测得的结果发送到液晶1602显示出来。

该系统对所测得的温度值进行分析,当温度高于或者低于设定的温度限时自动报警,并驱动相应的降温或加热设备,以达到对温度智能控制,从而使环境温度维持在设定的有利温度范围内。

系统总体结构图如图3-1
图3-1 温控系统总体结构框图
3.2温度控制系统的各个模块的方案论证
3.2.1 单片机控制芯片模块
方案一:PIC16C84单片机。

是8位CMOS EEPROM微控制器。

它有高性能的类似于RISC的指令,共有35条单字节的指令,所有的指令除程序分支指令需要两个指令周期外,都只需要一个指令周期。

程序指令的宽度为14位,在芯片内有1K×14的EEPROM程序存储器。

方案二:凌阳SPCE061A单片机。

该芯片拥有8路10位精度的ADC,两路10精度的DAC,只需要外接功放(SPY0030A)即可完成语音的播放。

另外凌阳十六位单片机具有易学易用的效率较高的一套指令系统和集成开发环境。

在此环境中,支持标准C语言,可以实现C语言与凌阳汇编语言的互相调用为软件开发提供了方便的条件。

SPCE061A片内还集成了一个ICE(在线仿真电路)接口,使得对该芯片的编程、仿真都变得非常方便,而ICE接口不占用芯片上的硬件资源,结合凌阳科技提供的集成开发环境(unSP IDE)用户可以利用它对芯片进行真实的仿真;而程序的下载(烧写)也是通过该接口进行下载。

方案三: AT89S52单片机。

是一种低功耗、高性能CMOS8位微控制器,具有 8K 在系统可编程Flash 存储器。

易失性存储与工业80C51 产品指令和引脚完全兼容。

在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得AT89S52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。

基于以上所述,考虑了制作成本和功耗,又根据系统需要选择设计选方案三。

3.2.2 键盘控制模块
方案一:独立式键盘。

如图3-2。

它是利用单片机I/O口读取口的电平高低来判断是否有键按下,这种方式的缺点是占用的I/O 口数较多。

图3-2
方案二:4×4矩阵键盘。

如图3-3。

矩阵键盘又称为行列式键盘,它是用4条I/O线作为行线,4
条I/O线作为列线组成的键盘。

在行线和列线的每一个交叉点上,设置一个按键。

这样键盘中按键的个数是4×4个。

这种行列式键盘结构能够有效地提高单片机系统中I/O口的利用率。

图3-3
基于以上所述,根据系统需要我选方案二。

3.2.3传感器测试电路模块
方案一:热敏电阻。

可满足40--90℃的测量范围,但热敏电阻精度、重复性、可靠性都比较差,对于检测小于1℃的温度信号是不适用的。

方案二:DS18B20温度传感器。

采用“一线总线”接口,测量温度范围为 -55°C到 +125°C,在-10到+85°C范围内,精度为±0.5°C。

现场温度直接以“一线总线”的数字方式传输,大大提高了系统的抗干扰性,适合于恶劣环境的现场温度测量,支持3V-5.5V的电压范围, DS18B20可以程序设定9-12位的分辨率,精度为±0.5°C。

综合上述,采用方案二。

3.2.4液晶显示模块
方案一:数显液晶模块。

是一种由段型液晶显示器件于专用的集成电路组装成一体的功能部件,只能显示数字和一些标识符号。

段型液晶显示器件大多应用在便携、袖珍设备上。

方案二:液晶点阵字符模块。

它是由点阵字符液晶显示器件和专用的行、列驱动器、控制器及必要的连接件,结构件装配而成的,可以显示数字和西文字符。

这种点阵字符模块本身具有字符发生器,显示容量大,功能丰富。

方案三:点阵图形液晶模块。

模块也是点阵模块的一种,其特点是点阵像素连续排列,行和列在排布中均没有空格。

因此可以显示连续、完整的图形。

考虑到实用性和经济性,本设计选择方案二。

第四章 DS18B20
的简介
4.1应用
18B20数字温度传感器接线方便,封装成后可应用于多种场合,如管道式,螺纹式,磁铁吸附式,不锈钢封装式,型号多种多样,有LTM8877,LTM8874等等。

主要根据应用场合的不同而改变其外观。

封装后的DS18B20可用于电缆沟测温,高炉水循环测温,锅炉测温,机房测温,农业大棚测温,洁净
室测温,弹药库测温等各种非极限温度场合。

耐磨耐碰,体积小,使用方便,封装形式多样,适用于各种狭小空间设备数字测温和控制领域。

4.2主要部件
DS18B20内部结构主要由四部分组成:64位光刻ROM、温度传感器、非挥发的温度报警触发器TH 和TL、配置寄存器。

该装置信号线高的时候,内部电容器储存能量通由1线通信电路给片子供电,而且在低电平期间为片子供电直至下一个高电平的到来重新充电。

DS18B20的电源也可以从外部
3V-5 .5V的电压得到。

S18B20采用一线通信接口。

因为一线通信接口,必须在先完成ROM设定,否则记忆和控制功能将无法使用。

主要首先提供以下功能命令之一:1 )读ROM,2 )ROM匹配,3 )搜索ROM,4 )跳过ROM,5 )报警检查。

这些指令操作作用在没有一个器件的64位光刻ROM序列号,可以在挂在一线上多个器件选定某一个器件,同时,总线也可以知道总线上挂有有多少,什么样的设备。

4.3数据存储方式及计算方法
DS18B20中的温度传感器可完成对温度的测量,以12位转化为例:用16位符号扩展的二进制补码读数形式提供,以0.0625℃/LSB形式表达,其中S为符号位。

这是12位转化后得到的12位数据,存储在18B20的两个8比特的RAM中,二进制中的前面5位是符号位,如果测得的温度大于0,这5位为0,只要将测到的数值乘于0.0625即可得到实际温度;如果温度小于0,这5位为1,测到的数值需要取反加1再乘于0.0625即可得到实际温度。

例如+125℃的数字输出为07D0H,+25.0625℃的数字输出为0191H,-25.0625℃的数字输出为FE6FH,-55℃的数字输出为FC90H .
第五章温度控制系
统的硬件部分
5.1主控芯片部分电路
图5-1
5.2各个模块电路
5.2.1温度测量模块
DS18B20通过P3.3口和AT89S52进行通讯。

GND为接地线, Q为数据输入输出接口,通过一个较弱的上拉电阻与单片机相连。

VCC为电源接口,既可由数据线提供电源,又可由外部提供电源,范围3.O~5.5 V。

其接口电路如图4-2.
图5-2 5.2.2实时时钟电路
利用DS1320芯片完成实时时钟的读取和设置,能实现对年、月、日、星期、时、分、秒进行记时,具有闰年补偿功能。

其工作电压为2.5伏到5.5伏,采用三线接口与CPU进行同步通信,并可采用突发方式一次传递多个字节的时钟信号或RAM数据。

其接口电路如图4-3.
图5-3
5.2.3液晶1602接口电路
字符型液晶模块1602是一种用5×7点阵图形来显示字符的液晶显示器,根据显示的容量可以分为1行16个字、2行16个字、2行20个字等等。

本设计用到的是最常用的2行16个字的1602液晶模块.接口电路如图4-4.
图5-4
5.2.4温度控制电路
当温度高于设定的温度上限时,驱动外围降温设备(这里用鼓风机来降温);当温度低于设定的温度下限时,驱动外围加热装置,以使温度维持在有利得范围内。

降温电路和加热电路分别如图4-5,4-6。

图5-5 降温电路
其中4N251,4N252代表光耦P251;Q5,Q6代表三极管9013;Q1~Q4代表达林顿管TIP132;B1代表直流电机。

继电器的选择:
方案一:常规电磁继电器
电磁继电器一般由铁芯、线圈、衔铁、触点簧片等组成的。

只要在线圈两端加上一定的电压,线圈中就会流过一定的电流,从而产生电磁效应,衔铁就会在电磁力吸引的作用下克服返回弹簧的拉力吸向铁芯,从而带动衔铁的动触点与静触点(常开触点)吸合。

当线圈断电后,电磁的吸力也随之消失,衔铁就会在弹簧的反作用力返回原来的位置,使动触点与原来的静触点(常闭触点)释放。

这样吸合、释放,从而达到了在电路中的导通、切断的目的。

对于继电器的“常开、常闭”触点,可以这样来区分:继电器线圈未通电时处于断开状态的静触点,称为“常开触点”;处于接通状态的静触点称为“常闭触点”。

继电器一般有两股电路,为低压控制电路和高压工作电路。

但由于有触电,有噪声,动作频率较低。

故不采用此方案。

方案二:固态继电器
固态继电器工作原理:
它是用半导体器件代替传统电接点作为切换装置的具有继电器特性的无触点开关器件,单相SSR为四端有源器件,其中两个输入控制端,两个输出端,输入输出间为光隔离,输入端加上直流或脉冲洗好到一定电流值后,输出端就能从断态转变成通态。

此系统中我们使用的继电器为
【型号】:MGR-1 DD220D25 【品名】:单相固态继电器25A 【控制方式】:直流控直流(DC-DC) 【负载电流】:25A 【负载电压】:5-220VDC 【控制电压】:3-32V/DC
由于固态继电器无触点,无噪音,动作频率可以很高。

固我们选用此方案。

电热丝的选择:
高温镍铬电热丝
由p = u*i 可以得出额定电流为1.3A ,因此上面所选继电器符合要求。

,SSR 的输入控制电压为3.2—32V 。

控制电流为5—30mA. ,由于单片机的输出电流较小,带载能力较弱,固需外加三极管驱动。

图5-6 加热电路
标定功率 w 额定电压 v 钢丝直径 mm 炉丝外径 mm 炉丝长度(参考值)
mm 炉丝重量 g 300 220
0.25
3.7
180
1.9
5.2.5键盘控制部分
采用4×4矩阵键盘的形式。

(1)原理图
图5-7
(2)按键说明
K4 ---设定闹钟使能与禁止。

按K4键后,LCD1602的第二行的最右边有小喇叭显示,闹钟使能。

再按K4键,不显示小喇叭,闹钟禁止。

K3 ---时间设定键。

设定顺序:年,月,日,星期,时,分,秒。

被选中的设定位闪动。

K2 ---加键。

设定数增加
K1 ---减键。

设定数减少
每当有键按下,蜂鸣器会响一声。

双键功能:
K1 ---+K2
先按住K1,然后再按K2,写入程序默认时间值。

06/05/01 Week:1
Time: 23:59:00
K1 ---+K3
先按住K1,然后再按一下K3,程序进入查看定时时间值。

06/05/01 Week:1
Alarm:23:59:00 ×←小喇叭显示
此界面显示2-3秒后,返回到正常时间显示界面
K1 ---+K4
先按住K1,然后再按一下K4,程序进入设定定时时间值。

设定顺序:时,分。

(K4键选择)
被选中的设定位闪动。

K2 ---加键。

设定数增加
K1 ---减键。

设定数减少
每当有键按下,蜂鸣器会响一声。

当定时时间与现行时间相等时,蜂鸣器响一分钟。

可以按K4键止闹。

5.2.6蜂鸣器报警模块
(1)控制端口为P3.7,其接口电路如图4-8.
图5-8
(2)工作原理
单片机通过P3.7来控制蜂鸣器的工作与关闭。

当P3.7=0时,PNP三级管导通,蜂鸣器开始工作。

从而单片机只需要P3.7输出0或者1开控制鉴别鸣器即可。

(3)、功能说明
当温度高于设定的温度上限40℃时,蜂鸣器响一声,说明温度过限,这时驱动降温设备降温;
当温度高于设定的温度下限20℃时,蜂鸣器响一声,说明温度低限,这时驱动加热设备加热。

第六章软件部分
6.1主程序流程图
图5-1主程序流程图
6.2各模块工作流程图
6.2.1 DS18B20采集计算温度流程图
图6-2 DS18B20采集计算温度流程图
6.2.2键处理子程序流程图
第七章系统调试
7.1硬件调试
硬件调试的主要任务是排除硬件故障,其中包括设计错误和工艺性故障。

用万用表逐步按照电路原理图检查电路板中所有器件的各引脚,尤其是电源的连接是否正确;检查各开关按键是否能正常开关,是否连接正确;各限流电阻是否短路等。

为了保护芯片,应先对各IC座(尤其是电源端)电位进行检查,确定其无误后再插入芯片检查。

可以通过一些简单的测试程序来查看接各硬件是否联接正常。

7.2软件调试
程序的调试应一个模块一个模块地进行,首先单独调试各功能子程序,检验程序是否能够实现预期
模块间能否正确传递参数,特别要注意各子程序的现场保护与恢复。

7.3测试结果与性能分析
从测量数据的对比我们可得出本系统所测温度是可靠的,静态误差方面可以达到0.18℃的误差,温度控制范围也与设定的温度上下限相吻合,对一般的工业生产完全可以采用本设计。

第八章
总结
本系统以AT89S52单片机为控制核心,利用其强大的处理能力,以及丰富的外围接口,再配合DS18B20温度传感器、液晶1602、DS1302等,很好的完成了实时温度的检测与显示,并当系统检测到温度高于设定的温度上限时准确的驱动鼓风机运转降温且发出报警;当温度低于设定的温度下限时继电器吸合代表加热指示。

此外,本系统还能实现万年历功能,显示并可设置年、月、日、星期、小时、分钟和秒,而且还能设置闹钟提醒。

因此本系统已基本符合了设计要求,在温度控制方面具有一定的先进性,可用于一般的工业生产温度控制。

附录1 元件清单.
附录2 系统测试仪器
仪器名称型号指标数量单片机开发板ME500 1 双通道示波器YB4365 100MHz 1 万用表MODEL MF47 1 直流稳压电源DF1731SC5A -5V—+5V 1 PC机ISPlay、Keil 软件 1
附录3 印制板图
附录4 开发板实物图
附录5 源程序
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define LCD_DATA 1 // Data
sbit LCD_RS = P2^0;
sbit LCD_RW = P2^1;
sbit LCD_EN = P2^2;
sbit LCD_LED = P2^6;
sbit K1 = P1^4;
sbit K2 = P1^5;
sbit K3 = P1^6;
sbit K4 = P1^7;
sbit reset = P1^2;
sbit sclk = P1^0;
sbit io = P1^1;
sbit DQ = P3^3;
sbit BEEP = P3^7;
sbit JDQ1=P2^3;//驱动电动机(0表示接通,1表示关闭)
bit year=0,month=0,day=0,week=0;
bit alarm_flag=0;
sfr DBPort = 0x80; //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口uchar timecount=0,count=0;
uchar temp_value; //温度值
uchar digital;
uchar TempBuffer[7];
unsigned char frq;
uchar str1[]=" - - Week: ";
uchar str2[]=" ";
uchar str3[]="Alarm: ";
uchar init [] ={0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //
uchar init1[] ={0x00,0x00};
uchar init2[] ={0x00,0x59,0x23,0x11,0x06,0x03,0x08}; //
//秒,分,时,日,月,星期,年
uchar bj_time[] ={0x00,0x00,0x00};
//秒,分,时
uchar code mytab[8] = {0x01,0x1b,0x1d,0x19,0x1d,0x1b,0x01,0x00};//小喇叭#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
void Set_W1302(uchar addr);
void Set_Flash(uchar row,uchar col);
void Set_place(uchar row,uchar col);
void Play_nowtime();
void key_set(uchar num,uchar row,uchar col );
void key_set_1(uchar num,uchar row,uchar col );
void alarm_time();
void Play_alarmtime();
void Time_compare();
void Init_DS18B20(void);
unsigned char ReadOneChar(void);
void WriteOneChar(uchar dat);
void ReadTemp(void);
void temp_to_str(void);
void Print(unsigned char *str);
void LCD_Write(bit style, unsigned char input);
unsigned char LCD_Wait(void);
void Read_DS18B20(void);
void speak(void);
void delayms(unsigned char ms);
void beep_temp();
void dianji(void);
void delay1(int ms)
{
unsigned char y;
while(ms--)
for(y = 0; y<250; y++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
/******************************************************************/ /* */ /*检查LCD忙状态*/ /*lcd_busy为1时,忙,等待。

lcd-busy为0时,闲,可写指令与数据。

*/ /* */ /******************************************************************/ bit lcd_busy()
{
bit result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
delayNOP();
result = (bit)(P0&0x80);
LCD_EN = 0;
return(result);
}
/*********************************************************/
/* */
/*写指令数据到LCD */
/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。

*/
/* */
/*********************************************************/
void lcd_wcmd(uchar cmd)
{
while(lcd_busy());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
P0 = cmd;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
/*********************************************************/
/* */
/*写显示数据到LCD */ /*RS=H,RW=L,E=高脉冲,D0-D7=数据。

*/ /* */
/*********************************************************/ void lcd_wdat(uchar dat)
{
while(lcd_busy());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
/*********************************************************/
/* */
/* LCD初始化设定*/ /* */
/*********************************************************/ void init_lcd()
{
delay1(15);
lcd_wcmd(0x01); //清除LCD的显示内容
lcd_wcmd(0x38); //16*2显示,5*7点阵,8位数据
delay1(5);
lcd_wcmd(0x38);
delay1(5);
lcd_wcmd(0x38);
delay1(5);
lcd_wcmd(0x0c); //显示开,关光标
delay1(5);
lcd_wcmd(0x06); //移动光标
delay1(5);
lcd_wcmd(0x01); //清除LCD的显示内容
delay1(5);
}
/*********************************************************/
//
/*********************************************************/ void delay()
{
uchar j;
for(j=250;j>0;j--);
}
/*********************************************************/
/* */
/* 写字符串函数*/
/* */
/*********************************************************/ void write_str(uchar addr,uchar *p)
{
uchar i=0;
lcd_wcmd(addr);
while(p[i]!='\0')
{
lcd_wdat(p[i]);
i++;
}
}
/*********************************************************/
/* */
/* 设定显示位置*/
/* */
/*********************************************************/ void write_position(uchar row,uchar col)
{
uchar place;
if(row==1)
{
place=0x80+col-1;
lcd_wcmd(place);
}
else
{
place=0xc0+col-1;
lcd_wcmd(place);
}
}
/*********************************************************/
/* */
/*自定义字符写入CGRAM */ /* */
/*********************************************************/ void writetab()
{
unsigned char i;
lcd_wcmd(0x40); //写CGRAM
for (i = 0; i< 8; i++)
lcd_wdat(mytab[i]);
}
/**********************************************************/ //
/**********************************************************/ void write_byte(uchar inbyte)
{
uchar i;
for(i=0;i<8;i++)
{
sclk=0; //写的时候低电平改变数据
if(inbyte&0x01)
io=1;
else
io=0;
sclk=1; //写的时候高电平,把数据写入ds1302
_nop_();
inbyte=inbyte>>1;
}
}
/**********************************************************/ /**********************************************************/ uchar read_byte() //sclk的下跳沿读数据
{
uchar i,temp=0;
io=1; //设置为输入口
for(i=0;i<7;i++)
{
sclk=0;
if(io==1)
temp=temp|0x80;
else
temp=temp&0x7f;
sclk=1; //产生下跳沿
temp=temp>>1;
}
return (temp);
}
/**********************************************************/ // 往ds1302的某个地址写入数据
/**********************************************************/ void write_ds1302(uchar cmd,uchar indata)
{
sclk=0;
reset=1;
write_byte(cmd);
write_byte(indata);
sclk=0;
reset=0;
}
/**********************************************************/ // 读ds1302某地址的的数据
/**********************************************************/ uchar read_ds1302(uchar addr)
{
uchar backdata;
sclk=0;
reset=1;
write_byte(addr); //先写地址
backdata=read_byte(); //然后读数据
sclk=0;
reset=0;
return (backdata);
}
/**********************************************************/ // 设置初始时间
/**********************************************************/ void set_ds1302(uchar addr,uchar *p,uchar n) //写入n个数据
{
write_ds1302(0x8e,0x00); //写控制字,允许写操作
for(;n>0;n--)
{
write_ds1302(addr,*p);
p++;
addr=addr+2;
}
write_ds1302(0x8e,0x80); //写保护,不允许写
}
/**********************************************************/ // 读取当前时间
/**********************************************************/ void read_nowtime(uchar addr,uchar *p,uchar n)
{
for(;n>0;n--)
{
*p=read_ds1302(addr);
p++;
addr=addr+2;
}
}
/**********************************************************/ // 初始化DS1302
/**********************************************************/ void init_ds1302()
{
reset=0;
sclk=0;
write_ds1302(0x80,0x00);
write_ds1302(0x90,0xa6); //一个二极管+4K电阻充电
write_ds1302(0x8e,0x80); //写保护控制字,禁止写
}
/**********************************************************/ /* */ /* 蜂鸣器响一声*/ /* */ /**********************************************************/ void beep()
{
unsigned char y;
for (y=0;y<100;y++)
{
delay();
BEEP=!BEEP; //BEEP取反
}
BEEP=1; //关闭蜂鸣器
delay1(50);
}
/**********************************************************/ /* */ /* :闪动函数*/ /* */ /**********************************************************/ void flash()
{
if(flag)
{
write_position(2,3);
lcd_wdat(':');
write_position(2,6);
lcd_wdat(':');
}
else
{
write_position(2,3);
lcd_wdat(0x20);
write_position(2,6);
lcd_wdat(0x20);
}
}
/**********************************************************/ // 主函数
/**********************************************************/ void main()
{
LCD_LED=0;
P1=0xff;
TMOD=0x01;
TH0=0x4c; //50ms定时
TL0=0x00;
EA=1;
ET0=1;
TR0=1;
Init_DS18B20( ) ; //DS18B20初始化
init_lcd(); //初始化LCD
write_str(0x80,str1); //液晶显示提示信息
write_str(0xc0,str2); //液晶显示提示信息
init_ds1302(); //初始化ds1302
writetab(); //自定义字符写入CGRAM
// delay1(5);
// write_position(2,16);
// lcd_wdat(0x00); //显示自定义字符小喇叭
// Read_DS18B20();
while(1)
{
//---------------------------------------------------------
// Read_DS18B20();
if(!K1)
{
if(!K2)
{
set_ds1302(0x80,init2,7); //设置初始时间,日期,年月
beep();
}
if(!K3)
{
write_str(0xc0,str3); //显示报警信息
if(alarm_flag) //alarm_flag=1,开定时
{
write_position(2,16);
lcd_wdat(0x00); //显示自定义字符小喇叭
}
Play_alarmtime(); //查看报警时间
beep();
delay1(700);
write_str(0xc0,str2); //显示时间信息
if(alarm_flag) //alarm_flag=1,开定时
{
write_position(2,16);
lcd_wdat(0x00); //显示自定义字符小喇叭
}
}
if(!K4)
{
alarm_time(); //K4键设定报警时间
if(alarm_flag) //alarm_flag=1,开定时
{
write_position(2,16);
lcd_wdat(0x00); //显示自定义字符小喇叭
}
}
}
//---------------------------------------------------------
if(!K2)
{
if(!K3)
{
}
if(!K4)
{
}
}
//---------------------------------------------------------
if(!K4)
{
beep();
alarm_flag=~alarm_flag;
if(alarm_flag) //alarm_flag=1,开定时
{
write_position(2,16);
lcd_wdat(0x00); //显示自定义字符小喇叭
}
else
{
write_position(2,16);
lcd_wdat(0x20); //显示自定义字符小喇叭
}
}
//---------------------------------------------------------
if(!K3&flag) //开始设定时间
{
write_ds1302(0x8e,0x00); //写保护控制字,允许写
write_ds1302(0x80,0x80); //停止时钟运行
write_ds1302(0x8e,0x80); //写保护控制字,禁止写
beep();
year=1;
count=((init[6]&0xf0)>>4)*10+(init[6]&0x0f); //读当前年数据
}
while(year) //设定年
{
Read_DS18B20();
key_set(99,1,1);
if(!K3)
{
Set_W1302(0x8c);
Set_place(1,1);
year=0;
month=1;
count=((init[4]&0xf0)>>4)*10+(init[4]&0x0f); //读当前月数据
}
}
while(month) //设定月
{
Read_DS18B20();
key_set_1(12,1,4);
if(!K3)
{
Set_W1302(0x88);
Set_place(1,4);
month=0;
day=1;
count=((init[3]&0xf0)>>4)*10+(init[3]&0x0f); //读当前日数据
}
}
while(day) //设定日
{
Read_DS18B20();
key_set_1 (31,1,7);
if(!K3)
{
Set_W1302(0x86);
Set_place(1,7);
day=0;
week=1;
count=init[5]&0x0f; //读当前星期数据
}
}
while(week) //设定星期
{
Read_DS18B20();
if(!K2)
{
beep();
if(count!=7)
count++;
else count=1;
}
if(!K1)
{
beep();
if(count!=1)
count--;
else count=7;
}
init1[1]=count%10;
if(flag)
{
write_position(1,15);
lcd_wdat(init1[1]+0x30);
}
else
{
write_position(1,15);
lcd_wdat(0x20);
}
if(!K3)
{
Set_W1302(0x8a);
write_position(1,15);
lcd_wdat(init1[1]+0x30);
week=0;
hour=1;
count=((init[2]&0xf0)>>4)*10+(init[2]&0x0f); //读当前时数据
}
}
while(hour) //设定时
{
Read_DS18B20();
key_set(23,2,1);
if(!K3)
{
Set_W1302(0x84);
Set_place(2,1);
hour=0;
min=1;
count=((init[1]&0xf0)>>4)*10+(init[1]&0x0f); //读当前分数据
}
}
while(min) //设定分
{
Read_DS18B20();
key_set(59,2,4);
if(!K3)
{
Set_W1302(0x82);
Set_place(2,4);
min=0;
sec=1;
count=((init[0]&0xf0)>>4)*10+(init[0]&0x0f); //读当前秒数据
}
}
while(sec) //设定秒
{
Read_DS18B20();
key_set(59,2,7);
if(!K3)
{
Set_W1302(0x80);
Set_place(2,7);
sec=0;
count=0;
}
}
Read_DS18B20();
Play_nowtime();
Time_compare();
}
}
/**********************************************************/
// Time0中断函数
/**********************************************************/ void Time0(void) interrupt 1 using 0
{
TH0=0x4c; //50ms定时
TL0=0x00;
timecount++;
if(timecount>8)
{
timecount=0;
flag=~flag;
}
}
/**********************************************************/ // 设定值写入DS1302
/**********************************************************/ void Set_W1302(uchar addr)
{
uchar temp;
write_ds1302(0x8e,0x00);
temp=(init1[0]<<4)+init1[1];
write_ds1302(addr,temp);
write_ds1302(0x8e,0x80);
beep();
}
/**********************************************************/ // 被设置数据闪动
/**********************************************************/ void Set_Flash(uchar row,uchar col )
{
init1[0]=count/10;
init1[1]=count%10;
if(flag)
{ //显示
write_position(row,col);
lcd_wdat(init1[0]+0x30);
write_position(row,col+1);
lcd_wdat(init1[1]+0x30);
}
else
{ //清屏
write_position(row,col);
lcd_wdat(0x20);
write_position(row,col+1);
lcd_wdat(0x20);
}
}
/**********************************************************/ // 指定位置显示
/**********************************************************/ void Set_place(uchar row,uchar col)
write_position(row,col);
lcd_wdat(init1[0]+0x30);
write_position(row,col+1);
lcd_wdat(init1[1]+0x30);
}
/**********************************************************/ // 显示当前时间
/**********************************************************/ void Play_nowtime()
{
read_nowtime(0x81,init,7); //读出当前时间,读出7个字节
write_position(2,1);
lcd_wdat(((init[2]&0xf0)>>4)+0x30);
write_position(2,2);
lcd_wdat('0'+(init[2]&0x0f)); //读小时
// write_position(2,3);
// lcd_wdat(':');
write_position(2,4);
lcd_wdat('0'+((init[1]&0xf0)>>4));
write_position(2,5);
lcd_wdat('0'+(init[1]&0x0f)); //读分钟
// write_position(2,6);
// lcd_wdat(':');
write_position(2,7);
lcd_wdat('0'+((init[0]&0xf0)>>4));
write_position(2,8);
lcd_wdat('0'+(init[0]&0x0f)); //读秒
write_position(1,1);
lcd_wdat('0'+((init[6]&0xf0)>>4));
write_position(1,2);
lcd_wdat('0'+(init[6]&0x0f)); //读年
// write_position(1,3);
// lcd_wdat('/');
write_position(1,4);
lcd_wdat('0'+((init[4]&0xf0)>>4));
write_position(1,5);
lcd_wdat('0'+(init[4]&0x0f)); //读月
// write_position(1,6);
// lcd_wdat('/');
write_position(1,7);
lcd_wdat('0'+((init[3]&0xf0)>>4));
write_position(1,8);
lcd_wdat('0'+(init[3]&0x0f)); //读日
write_position(1,15);
lcd_wdat('0'+(init[5]&0x0f)); //读周
flash();
}
/*********************************************************/ // 键设定函数
/*********************************************************/ void key_set(uchar num,uchar row,uchar col )
{
if(!K2)
{
beep();
if(count!=num)
count++;
else count=0;
}
if(!K1)
{
beep();
if(count!=0)
count--;
else count=num;
}
Set_Flash(row,col);
}
void key_set_1(uchar num,uchar row,uchar col )
{
if(!K2)
{
beep();
if(count!=num)
count++;
else count=1;
}
if(!K1)
{
beep();
if(count!=1)
count--;
else count=num;
}
Set_Flash(row,col);
}
/*********************************************************/ // 报警时间设定
/*********************************************************/ void alarm_time()
// if(!K4&flag) //开始设定报警时间
{
write_str(0xc0,str3); //液晶显示提示信息
Play_alarmtime();
beep();
hour=1;
count=((bj_time[2]&0xf0)>>4)*10+(bj_time[2]&0x0f); //读当前时报警数据
while(hour) //设定时
{
key_set(23,2,1);
if(!K4)
{
Set_place(2,1);
bj_time[2]=((init1[0]<<4)|init1[1]);
beep();
hour=0;
min=1;
count=((bj_time[1]&0xf0)>>4)*10+(bj_time[1]&0x0f); //读当前分报警数据
}
}
while(min) //设定分
{
key_set(59,2,4);
if(!K4)
{
Set_place(2,4);
bj_time[1]=((init1[0]<<4)|init1[1]);
beep();
min=0;
sec=0;
count=((bj_time[0]&0xf0)>>4)*10+(bj_time[0]&0x0f); //读当前秒报警数据
write_str(0xc0,str2); //液晶显示提示信息
}
}
/*
while(sec) //设定秒
{
key_set(59,2,7);
if(!K4)
{
Set_place(2,7);
bj_time[0]=((init1[0]<<4)|init1[1]);
beep();
min=0;
count=0;
write_str(0xc0,str2); //液晶显示提示信息
}
}*/
}
}
/*********************************************************/ // 报警时间显示
/*********************************************************/ void Play_alarmtime()
{
write_position(2,1);
lcd_wdat(((bj_time[2]&0xf0)>>4)+0x30);
write_position(2,2);
lcd_wdat('0'+(bj_time[2]&0x0f)); //读小时
write_position(2,3);
lcd_wdat(':');
write_position(2,4);
lcd_wdat('0'+((bj_time[1]&0xf0)>>4));
write_position(2,5);
lcd_wdat('0'+(bj_time[1]&0x0f)); //读分钟
write_position(2,6);
lcd_wdat(':');
write_position(2,7);
lcd_wdat('0'+((bj_time[0]&0xf0)>>4));
write_position(2,8);
lcd_wdat('0'+(bj_time[0]&0x0f)); //读秒
}
/*********************************************************/ // 时间比较
/*********************************************************/ void Time_compare()
{
if(alarm_flag)
{
if(init[2]==bj_time[2])
{
if(init[1]==bj_time[1])
beep();
}
}
}
/*********************************************************/ /***********ds18b20子程序*************************/
/***********ds18b20延迟子函数(晶振12MHz )*******/
{
while(i--);
}
/**********ds18b20初始化函数**********************/
void Init_DS18B20(void)
{
unsigned char x=0;
DQ = 1; //DQ复位
delay_18B20(20); //稍做延时
DQ = 0; //单片机将DQ拉低
delay_18B20(200); //精确延时大于480us
DQ = 1; //拉高总线
delay_18B20(40);
x=DQ; //稍做延时后如果x=0则初始化成功x=1则初始化失败delay1(2);
}
/***********ds18b20读一个字节**************/
unsigned char ReadOneChar(void)
{
uchar i=0;
uchar dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; // 给脉冲信号
dat>>=1;
DQ = 1; // 给脉冲信号
if(DQ)
dat|=0x80;
delay_18B20(20);
}
return(dat);
}
/*************ds18b20写一个字节****************/
void WriteOneChar(uchar dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
delay_18B20(10);
DQ = 1;
dat>>=1;
}
/**************读取ds18b20当前温度************/
void ReadTemp(void)
{
unsigned char a=0;
unsigned char b=0;
unsigned char t=0;
EA =0;
Init_DS18B20();
delay_18B20(200);
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
delay_18B20(200); // this message is wery important
Init_DS18B20();
delay_18B20(200);
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器)前两个就是温度delay_18B20(200);
a=ReadOneChar(); //读取温度值低位
delay_18B20(200);
b=ReadOneChar(); //读取温度值高位
//temp_value=a;
temp_value=b<<4;
temp_value+=(a&0xf0)>>4;
digital=(unsigned char)((a&0x0f)*0.0625*10);
EA =1;
}
void temp_to_str() //温度数据转换成液晶字符显示
{
TempBuffer[0]=temp_value/10+'0'; //十位
TempBuffer[1]=temp_value%10+'0'; //个位
TempBuffer[2]='.';
TempBuffer[3]=digital+'0';
TempBuffer[4]=0xdf; //温度符号
TempBuffer[5]='C';
TempBuffer[6]='\0';
}
void Print(unsigned char *str)
{
while(*str!='\0')
{
LCD_Write(LCD_DA TA,*str);
str++;
}
}
void LCD_Write(bit style, unsigned char input)
LCD_EN=0;
LCD_RS=style;
LCD_RW=0; _nop_();
DBPort=input; _nop_();//注意顺序
LCD_EN=1; _nop_();//注意顺序
LCD_EN=0; _nop_();
LCD_Wait();
}
unsigned char LCD_Wait(void)
{
LCD_RS=0;
LCD_RW=1; _nop_();
LCD_EN=1; _nop_();
LCD_EN=0;
return DBPort;
}
void Read_DS18B20(void) //温度采集及在液晶上显示{
temp_value=0;
ReadTemp(); //开启温度采集程序
temp_to_str(); //温度数据转换成液晶字符write_position(2,10); //液晶字符显示位置
Print(TempBuffer); //显示温度
dianji();
beep_temp();
/*if(temp_value>=40||temp_value<=20)
beep_temp();
if(temp_value>=40||temp_value<=20)
beep_temp();*/
}
void beep_temp()
{
unsigned char y;
if(temp_value>34||temp_value<=20)
{
for (y=0;y<200;y++)
{
delay();
delay();
BEEP=!BEEP; //BEEP取反
}
BEEP=1; //关闭蜂鸣器
}
}
void dianji(void)
JDQ1=0; //电机停止
if(temp_value>=32)
{
JDQ1=1; //电机起动
// Read_DS18B20();
}
else
{
JDQ1=0; //电机停止// Read_DS18B20();
}
}。

相关文档
最新文档