基于单片机的万年历_第1页
基于单片机的万年历_第2页
基于单片机的万年历_第3页
基于单片机的万年历_第4页
基于单片机的万年历_第5页
已阅读5页,还剩50页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

单片机系统设计、仿真与程序设计报告PAGE4单片机系统设计、仿真与程序设计报告题目:基于单片机的万年历姓名:班级:学号:指导教师:通信工程系2010年12月

设计目的《单片机原理及应用》是一门技术性、应用性很强的学科,实践教学是它的一个极为重要的环节。不论是硬件扩展、接口应用还是编程方法、程序调试,都离不开实验教学。如果不在切实认真地抓好学生的实践技能的锻炼上下功夫,单凭课堂理论课学习,势必出现理论与实践脱节,学习与应用脱节的局面。任随书本上把单片机技术介绍得多么重要、多么实用、多么好用,同学们仍然会感到那只是空中楼阁,离自己十分遥远,或者会因此而对它失去兴趣,或者会感到它高深莫测无从下手,这些情况都会令课堂教学的效果大打折扣。本次仿真设计的目的就是让同学们在理论学习的基础上,通过完成一个涉及MCS-51单片机多种资源应用并具有综合功能的小系统目标板的设计与编程应用,使学生不但能够将课堂上学到的理论知识与实际应用结合起来,而且能够对电子电路、电子元器件、印制电路板等方面的知识进一步加深认识,同时在软件编程、排错调试、焊接技术、相关仪器设备的使用技能等方面得到较全面的锻炼和提高,为今后能够独立进行某些单片机应用系统的开发设计工作打下一定的基础。设计任务叙述系统应该完成的功能,系统功能包括以下几点:(1)24小时计时功能用6位LED显示器显示时、分、秒。(2)时间调整功能用功能移位键、功能加键和功能减键实现时间的调整(3)闹铃功能用定闹键配合功能移位键、功能加键和功能减键三个按键设定闹铃,并用蜂鸣器实现响铃功能。(4)环境温度采集与显示功能选用温度传感器DS18B20采集环境温度,并用2位LED显示器显示环境温度。在这里我们只考虑采集室内温度,即零度以上的温度。硬件设计本次设计的万年历系统以单片机为主控芯片,通过读写日历时钟芯片和温度芯片来实时的改变当前时间和温度,并通过LED显示实时数据,同时辅助以键盘来调节显示时间和定时时间,并带有蜂鸣器,当定时时间到时闹钟即打开。硬件的结构和可靠性直接影响着整个系统的可靠性,所以合理的安排电路能提高电子产品的性能,但任何电子产品都必须有一个可靠的电源为其提供能量才能工作,本设计先介绍电源部分,再介绍功能电路。3.1电源设计电源的设计是电子产品的最基本模块,大部分电子产品都是用的直流电源,将220V的交流电转化为直流电也是我们必行的,电源的稳定性也直接影响着电子产品的性能,现在常用的直流稳压电源有变压器式和开关式电源两种。变压器式直流稳压源由电源变压器、整流电路、滤波电路和稳压电路四个部分组成,如图所示,交流电先经电源变压器变换成所须等级的交流电压,而后经整流电路将之整流成直流电,这时的直流电脉动量很大,经滤波电路以减小其脉动量,最后经稳压电路进行稳压,从而得出符合要求的电压。变压器式直流稳压电源结构简单,设计容易,但体积较大,效率也较低,过负载能力也差。图3-1变压器式直流稳压电源开关式直流稳压电源简称开关电源(SwitchingPowerSupply),它是指起电压调整功能的器件始终以开关方式工作的一种直流稳压电源。50Hz单相交流220V电压或三相交流220V380V电压经EMI防电磁干扰电源滤波器,直接整流滤波,然后再将滤波后的直流电压经变换电路变换为数赫或数百千赫的高频方波或准方波电压,通过高频变压器隔离并降压(或升压)后,再经高频整流、滤波电路,最后输出直流电压。通过取样、比较、放大及控制、驱动电路,控制变换器中功率开关管的占空比,便能得到稳定的输出电压。开关电源具有功耗小、效率高、体积小、重量轻、稳压范围宽、电路形式灵活多样等诸多优点,但成本高,因而本设计采用变压器式电源。3.2主电路设计主电路的功能是完成年、月、日、星期、时、分、秒之间的转换,对温度传感器进行控制并读取温度转换后的值,再送往LED显示,并且接受键盘操作,对日期和时间进行校正,同时还要判断定时时间是否到,定时到时闹铃打开。主电路原理图如图所示,显示部分用P0口做为输出数据接到LED数码管a到h,并接8个上拉电阻做为各段的驱动。用P3口的低3位接译码器的A0,A1,A2端,用P3.3,P3.4,P3.5分别接译码器的使能端,通过控制P3口来控制LED的动态扫描。单片机的18和19引脚接12MHZ的晶振,并接两个22PF的电容同时接地,单片机复位端接一极性电容并连接到电源处,在极性电容的负极接一10K的电阻,并连接至地做为放电用。本设计用到四个独立式键盘分别接到P1口的低4位,用P1口的P1.4,P1.5,P1.6接日历时钟的使能端和时钟端及数据输入输出口,并在日历时钟上接一32.768KHZ的晶振,并接两个22PF的电容终端和地相连,用P1.7接温度芯片的DQ引脚,作为温度数据或命令的读写,用单片机的P3.7接扬声器,作为发音电路,各芯片的电源部分分别接到有开关式电源产生的+5V电源上,芯片的接地端都接在公共地上,在这里接电源部分就不再一一详述,读者注意一下就行了。设计采用动态显示,轮流扫描各个LED使之显示相应的数型码,当扫描频率大于人眼所能识别的频率时就看不到闪烁现象。动态显示的亮度不如静态显示,但静态显示占用的I/O口资源较多,往往用移位寄存器74LS164等来扩充其I/O口不足的情况,当显示位数较多时,这样势必增加硬件开销,增大成本,不利于开阔市场。本设计的突出之处在于硬件电路简单,大大减少了硬件开销,这样又势必增加了软件开发的难度,但降低了成本有利于市场的开阔。3.3主控制器和外围器件主控芯片由单片机完成。目前市场上的单片机种类很多,如Intel公司生产的80C51系列,ATMEL公司生产的AT89系列,Microchip公司生产的PIC系列,ADI公司生产的高性能ADuC84X系列单片机和ATMEL公司的高性能ATmegaXXX系列单片机等等。本设计所要求的功能有限用一般的单片机即可完成任务,其中ATMEL公司生产的AT89系列单片机最为流行,它具有FlashROM,擦写方便,且价格便宜。因此选用AT89S52为主控芯片。外围器件其中温度传感器采用美国达拉斯(DALLAS)生产的可编程的DS18B20温度传感器。它直接输出数字量的温度值,精度高,测温分辨率可达0.0625℃。一线制总线,接口方便,体积小等诸多优点。时钟芯片选用DS1302,DS1302

是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能。显示部分采用共阴极数码管LED显示,具有显示亮度高,功耗小的优点,配合译码器74HC138完成动态显示功能。3.3.1AT89S52单片机AT89S52是一种低功耗、高性能CMOS8位微控制器,使用ATMEL公司高密度非易失性存储器技术制造,与工业80C51产品指令和引脚完全兼容。并具有以下标准功能:8k字节Flash,256字节RAM,32位I/O口线,看门狗定时器,2个数据指针,三个16位定时器/计数器,一个6向量2级中断结构,全双工串行口,片内晶振及时钟电路。另外,AT89S52可降至0Hz静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。3.3.2温度芯片DS18B20DS18B20数字温度计是DALLAS公司生产的1-Wire,即单总线器件,具有线路简单,体积小的特点。因此用它来组成一个测温系统,具有线路简单,在一根通信线,可以挂很多这样的数字温度计,十分方便。

图3-2DS1302封装DS18B20的引脚功能描述序号名称引脚功能描述1GND接地2DQ数据输入/输出引脚。漏极开路。当被用着在寄生电源下,也可以向器件提供电源。3VDD可选择的VDD引脚。当工作于寄生电源时,此引脚必须接地。表3-1DS18B20的引脚功能3.3.3DS18B20ROM操作指令一旦总线主机检测到从器件的存在,它便可以发出器件ROM操作命令之一。所有ROM操作命令均为8位长。读ROM[33h]:此命令允许总线主机读DS18B20的8位产品系列编码,唯一的48信序列号,以及8位的CRC。此命令只能在总线上仅有一个DS18B20的情况下使用。符合ROM[55h]:此命令后继以64位的ROM数据序列,允许总线主机对多点总线上特定的DS18B20寻址。只有与64位ROM序列严格相符的DS18B20才能对后继的存储器操作命令作出响应。跳过ROM[CCh]:在单点总线系统中,此命令通过允许总线主机不提供64位ROM编码而直接进行存储器操作以节省时间。搜索ROM[F0h]:当系统开始工作时,总线主机可能不知道单总线上的器件个数或不知道其64位ROM编码。搜索ROM命令允许总线控制器用排除法识别总线上的所有从器件的64位编码。警告搜索[ECh]:此命令的流程与搜索ROM命令相同。但是仅在最近一次温度测量出现警告的情况下,DS18B20才对此命令作出响应。3.3.4DS18B20RAM操作指令写暂存存储器[4Eh]:这个命令向DS18B20的暂存器TH和TL中写入数据。可以在任何时刻发出复信命令来中止写入。读暂存存储器[BEh]:这个命令读取暂相隔器的内容。读取将从第1个字节开始,一直进行下去,直到第9(CRC)字节读完。如果不想读完所有字节,控制器可以在任何时间发出复位命令来中止读取。复制暂存存储器[48h]:这个命令把暂存器的内容拷贝到DS18B20的E2ROM存储器里,即把温度报警触发字节存入非易失性存储器里。温度变换[44h]:这条命令启动一次温度转换而无需其它数据。温度转换命令被执行,而后DS18B20保持等待状态。如果总线控制器在这条命令之后跟着发出读时间隙,而DS18B20又忙于做温度转换的话,DS18B20将在总线上输出0,若温度转换完成,则输出1。如果使用寄生电顺势,总线控制器必须在发出这条命令后立即启动强上拉,并保持500ms以上时间。读忙[B8h]:在这条命令发出之后发出读数据隙,器件会输出温度转换忙的标识:0为忙,1为准备就绪。读电源[B4h]:若把这条命令发给DS18B20后,发出读时间隙,器件会返回它的电源模式:0为寄生电源,1为外部电源。3.3.5DS18B20的数据处理DS18B20的高速暂存存储器由9个字节组成,其分配如图2-2所示。当温度转换命令发布后,经转换所得的温度值以2字节补码形式存放在高速暂存存储器的第1、2个字节里。单片机可通过单总线接口读到该数据,读取时低位在前,高位在后。3.3.6日历时钟芯片DS1302DS1302

是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后背电源双电源引脚,同时提供了对后背电源进行涓细电流充电的能力。

DS1302的引脚排列,其中Vcc1为后备电源,VCC2为主电源。DS1302由Vcc1或Vcc2两者中的较大者供电。X1和X2是振荡源,外接32.768kHz晶振。RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。上电时,在Vcc≥2.5V之前,RST必须保持低电平。只有在SCLK为低电平时,才能将RST置为高电平。I/O为串行数据输入输出端(双向),后面有详细说明。SCLK始终是输入端。图3-3DS1302引脚图DS1302

的控制字如图所示。控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。1RAMA4A3A2A1A0RAMCKCK表3-2DS1302控制字在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。

DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式,其日历、时间寄存器及其控制字见下表。寄存器命令码数据范围寄存器中各位的内容名称地址写读76543210秒00H80H81H00~59CH秒数据分01H82H83H00~590分数据时02H84H85H01~12或00~2312/24010/AP时数据日03H86H87H01~28,2930,3100日数据月04H88H89H01~12000月数据星期05H9AH8BH01~0700000星期数据年06H8CH8DH00~99年数据多字节读写BEHBFH——表3-3日历时间寄存器3.3.7数码管LEDLED显示器由若干个发光二极管组成,当发光二极管导通时,相应的一个笔画或一个点就发光。控制相应的管导通,就能显示出对应字符。各段LED显示器需要由驱动电路驱动。在七段LED显示器中,通常将各段发光二极管的阴极或阳极连在一起作为公共端。将各段发光二极管连在一起的叫共阳极显示器,用低电平驱动;将阴极连在一起的叫共阴极显示器,用高电平驱动。静态显示就是每一个显示器各笔画段都要独占具有一个锁存功能的输出口线,CPU把要显示的字形代码送到输出口上,就可以使显示器上显示所需的数字或符号,此后,即使CPU不在去访问它,因为各笔画段借口具有锁存功能,显示的内容也不会消失。动态显示是指显示器显示某一字符时,相应段的发光二极管恒定地导通或截止。静态显示有并行输出和串行输出两种方式。在本系统中数码管使用共阴极接法而且是用动态显示。3.3.8译码器74HC13874HC138译码器是通过3条线来达到控制8条线的状态,就是通过3条控制线A0、A1、A2不同的高低电平组合来控制Y0~Y7的输出状态,其中4和5为使能地端,与8引脚共同接地,当接高电平时Y0到Y7输出高电平。6号脚为使能端,为高电平时有效。74HC138封装如图2-5。当需要级联时只需要改变使能端信号引脚即可,连接方法简单。图3-474HC138封装图软件仿真软件设计是本设计的关键,软件程序编写的好坏直接影响着系统运行情况的良好。因本程序涉及的模块较多,所以程序编写也采用模块化设计,C语言具有编写灵活、移植方便、便于模块化设计的特点,所以本系统的软件采用C51编写。4.1程序框图判断是否有按键按下时间、日期、上限温度、闹钟设置模块没有按键按下判断是否有按键按下时间、日期、上限温度、闹钟设置模块没有按键按下温度检测模块开机初始化显示欢迎界面从DS1302读取信息1602液晶显示相关信息4.2源程序代码#include<reg52.h>#include<intrins.h>unsignedcharcodedisplaywelcome[]={"WelcomeToMyLcdTimer"};//欢迎界面unsignedcharcodedisplaywish[]={"HappyEveryDay^_^"}; //欢迎界面unsignedcharcodeovertemperature[]={"OVERTEMPERATURE!"};unsignedcharcodedigit[]={"0123456789"}; //数字代码unsignedcharmode,TH,TL,TN,TD,length,tempswitch,Maxtemp=40,amode,alarmmode,minutes,hours,minutea,seconds,houra=12;sbitSCLK=P1^0; //DS1302时钟输入sbitDATE=P1^1; //DS1302数据输入 sbitREST=P1^2; //DS1302复位端口sbitSET=P1^4; //DS1302设置模式选择位sbitADD=P1^5; //增加sbitRED=P1^6; //减小sbitCANL=P1^7;voiddelay1ms(inti)//1毫秒延时{intj,k;while(i--)for(j=76;j>1;j--);for(k=29;k>1;k--); }voiddelaynus(unsignedcharn)//延时若干微秒{unsignedchari;for(i=0;i<n;i++); }/***********蜂鸣器模块************/sbitbeep=P3^6; //位定义,定义P.6位fmpvoiddely500(void){unsignedchari;for(i=250;i>0;i--){_nop_();}}voidbaojing(unsignedcharn){unsignedcharx,i;while(n--){for(i=0;i<5;i++){for(x=0;x<200;x++) { beep=~beep; dely500(); }}for(i=0;i<3;i++){ for(x=0;x<200;x++) { beep=~beep; dely500(); dely500(); }}}}/*******DS1302模块*************/voidWrite1302(unsignedchardate)//向1302写数据{ unsignedchari; SCLK=0; delaynus(2); for(i=0;i<8;i++) { DATE=date&0x01; SCLK=1; delaynus(2); SCLK=0; delaynus(2); date>>=1; }}voidWriteSet1302(unsignedcharcmd,unsignedchardate)//根据相应的命令输入相应的数据{ REST=0; SCLK=0; REST=1; Write1302(cmd); delaynus(5); Write1302(date);SCLK=1; REST=0;}unsignedcharRead1302(void) //读取1302数据{ unsignedchari,date; delaynus(2); for(i=0;i<8;i++) { date>>=1; if(DATE==1) date|=0x80; SCLK=1; delaynus(2); SCLK=0; delaynus(2); } returndate;}unsignedcharReadSet1302(unsignedcharcmd)//根据命令读取1302相应的值{ unsignedchardate; REST=0; SCLK=0; REST=1; Write1302(cmd); delaynus(2); date=Read1302(); SCLK=1; REST=0; returndate;}voidIntDS1302(void)//DS1302初始化{ unsignedcharflag;flag=ReadSet1302(0x81); if(flag&0x80) {//判断时钟芯片是否关闭WriteSet1302(0x8E,0x00);//根据写状态寄存器命令字,写入不保护指令 WriteSet1302(0x80,((0/10)<<4|(0%10)));//根据写秒寄存器命令字,写入秒的初始值 WriteSet1302(0x82,((0/10)<<4|(0%10)));//根据写分寄存器命令字,写入分的初始值 WriteSet1302(0x84,((0/10)<<4|(0%10)));//根据写小时寄存器命令字,写入小时的初始值 WriteSet1302(0x86,((0/10)<<4|(0%10)));//根据写日寄存器命令字,写入日的初始值 WriteSet1302(0x88,((0/10)<<4|(0%10)));//根据写月寄存器命令字,写入月的初始值WriteSet1302(0x8c,((10/10)<<4|(10%10)));//根据写年寄存器命令字,写入年的初始值 WriteSet1302(0x90,0xa5);//打开充电功能选择2K电阻充电方式 WriteSet1302(0x8E,0x80); //根据写状态寄存器命令字,写入保护指令}}/***************液晶显示模块*****************/sbitRS=P2^5;sbitRW=P2^6;sbitE=P2^7;sbitBF=P0^7;/*液晶忙检测*/bitBusyTest(void){ bitresult; RS=0; RW=1; E=1; _nop_(); _nop_(); _nop_(); result=BF; _nop_(); _nop_(); _nop_(); E=0; returnresult;}/*写指令*/voidWrite_com(unsignedcharcommand){ while(BusyTest()!=0); RS=0; RW=0; E=0; _nop_(); _nop_(); _nop_(); P0=command; _nop_(); _nop_(); _nop_(); E=1; _nop_(); _nop_();_nop_(); E=0;}/*写地址*/voidWrite_Address(unsignedcharaddress){ Write_com(address|0x80); delay1ms(1); }/*写数据*/voidWrite_Date(unsignedchardate){ RS=1; RW=0; E=0; _nop_(); _nop_(); _nop_(); P0=date; _nop_(); _nop_(); _nop_(); E=1; _nop_(); _nop_(); _nop_(); E=0; delay1ms(1);}/*初始化*/voidLcd_Int(void){ Write_com(0x38); delay1ms(1); Write_com(0x38); delay1ms(1); Write_com(0x06); delay1ms(1); Write_com(0x0c); delay1ms(1); Write_com(0x01); }voiddisplaymainpart(void)//显示液晶主要部分(不变化部分){Write_Address(0x01); delay1ms(1); Write_Date('D'); Write_Date('A'); Write_Date('T'); Write_Date('E'); Write_Date(':'); delay1ms(1); Write_Address(0x0A); delay1ms(1); Write_Date('-'); Write_Address(0x0D); Write_Date('-'); Write_Address(0x42); Write_Date('T'); Write_Date('I'); Write_Date('M'); Write_Date('E'); Write_Date(':'); Write_Address(0x4A); Write_Date('-'); Write_Address(0x4D); Write_Date('-'); Write_Address(0x06); Write_Date('2'); Write_Date('0');}voiddisplay_Second(unsignedcharsecond)//在液晶上显示秒{ unsignedchari,j; i=second/10; j=second%10; Write_Address(0x4E); Write_Date(digit[i]); Write_Date(digit[j]); delay1ms(1);}voiddisplay_Minute(unsignedcharminute)//在液晶上显示分{ unsignedchari,j; i=minute/10; j=minute%10; Write_Address(0x4B); Write_Date(digit[i]);Write_Date(digit[j]); delay1ms(1);}voiddisplay_Hour(unsignedcharhour)//在液晶上显示时{ unsignedchari,j; i=hour/10; j=hour%10; Write_Address(0x48); Write_Date(digit[i]); Write_Date(digit[j]); delay1ms(1);}voiddisplay_Day(unsignedcharday) //在液晶上显示日{ unsignedchari,j; i=day/10; j=day%10; Write_Address(0x0E); Write_Date(digit[i]); Write_Date(digit[j]); delay1ms(1);}voiddisplay_Month(unsignedcharmonth) //在液晶上显示月{ unsignedchari,j; i=month/10; j=month%10; Write_Address(0x0B); Write_Date(digit[i]); Write_Date(digit[j]); delay1ms(1);}voiddisplay_Year(unsignedcharyear)//在液晶上显示年{ unsignedchari,j; i=year/10; j=year%10; Write_Address(0x08); Write_Date(digit[i]); Write_Date(digit[j]); delay1ms(1);}voiddisplay_houra(unsignedcharx) //闹钟小时部分显示{ unsignedchari,j; i=x/10; j=x%10; Write_Address(0x44); Write_Date(digit[i]); Write_Date(digit[j]); }voiddisplay_minutea(unsignedcharx)//闹钟分钟部分显示{ unsignedchari,j; i=x/10; j=x%10; Write_Address(0x47); Write_Date(digit[i]); Write_Date(digit[j]);}voiddisplay_Time(void) //显示实时时间{ unsignedcharvalue,day,month,year; Write_com(0x0c); value=ReadSet1302(0x81); seconds=(((value&0x70)>>4)*10+(value&0x0f)); display_Second(seconds); value=ReadSet1302(0x83); minutes=(((value&0x70)>>4)*10+(value&0x0f)); display_Minute(minutes); value=ReadSet1302(0x85); hours=(((value&0x70)>>4)*10+(value&0x0f)); display_Hour(hours); value=ReadSet1302(0x87); day=(((value&0x70)>>4)*10+(value&0x0f)); display_Day(day); value=ReadSet1302(0x89); month=(((value&0x70)>>4)*10+(value&0x0f)); display_Month(month); value=ReadSet1302(0x8D); year=(((value&0xf0)>>4)*10+(value&0x0f)); display_Year(year);}voiddisplaystar(void)//显示欢迎界面{ unsignedchari,j; Write_Address(0x0f);while(displaywelcome[i]!='\0') { Write_Date(displaywelcome[i]); i++; delay1ms(1); } i=0; Write_Address(0x4f); while(displaywish[i]!='\0') { Write_Date(displaywish[i]); i++; delay1ms(1); } j=40; while(j--) { Write_com(0x18);//循环左移 delay1ms(700); } Write_com(0x01); delay1ms(10);}voidgbdisplay(unsignedcharaddress)//时间调整时光标闪烁{ Write_Address(address); delay1ms(5); Write_com(0x0f); delay1ms(5); }voiddisplaymaxt(unsignedcharx)//显示最大温度{ unsignedchari,j,k; Write_com(0x0c); delay1ms(2); Write_Address(0x44); i=x/100; j=x/10; k=x%10; Write_Date(digit[i]); Write_Date(digit[j]); Write_Date(digit[k]); }/*****************时间调整部分*********************/voidhourset(void) //调时{ unsignedchartimevalue,hour; delay1ms(500); //防止多次触发 WriteSet1302(0x8e,0x00);//将写保护去掉,确保能正常将调整后的数值写入DS1302 timevalue=ReadSet1302(0x85);//读取此时的数值 hour=(((timevalue&0x70)>>4)*10+(timevalue&0x0f)); while(1) { if(ADD==0) { delay1ms(50); if(ADD==0) { hour++; delay1ms(300); while(ADD==0); } } if(RED==0) { delay1ms(50); if(RED==0) { hour--; delay1ms(300); if(hour==0)hour=23; while(RED==0); } } timevalue=(((hour)/10)<<4|(hour%10)); WriteSet1302(0x84,timevalue); delay1ms(1); display_Hour(hour); Write_Address(0x49); delay1ms(5); if(hour>=24)hour=0; delay1ms(5); if(CANL==0) { mode=0; Write_com(0x0c); break; } if(SET==0)break; } WriteSet1302(0x8e,0x80);}voidminuteset(void) //调分{ unsignedchartimevalue,minute; delay1ms(500); WriteSet1302(0x8e,0x00); timevalue=ReadSet1302(0x83); minute=(((timevalue&0x70)>>4)*10+(timevalue&0x0f)); while(1) { if(ADD==0) { delay1ms(10); if(ADD==0) { minute++; if(minute>=60)timevalue=0; while(ADD==0); } } if(RED==0) { delay1ms(10); if(RED==0) { minute--; delay1ms(300); if(minute==0)minute=59; while(RED==0); } } timevalue=((minute/10)<<4|(minute%10)); WriteSet1302(0x82,timevalue); delay1ms(1); display_Minute(minute); Write_Address(0x4c); delay1ms(5); if(minute>=60)minute=0; delay1ms(5); if(CANL==0) { mode=0; Write_com(0x0c); break; } if(SET==0)break; } WriteSet1302(0x8e,0x80);}voidsecondset(void) //秒归零{ unsignedcharsecond; delay1ms(500); WriteSet1302(0x8e,0x00); while(1) { if(ADD==0) { delay1ms(10); if(ADD==0) { second=0; WriteSet1302(0x80,0x00); while(ADD==0); } } delay1ms(1); display_Second(second); Write_Address(0x4f); delay1ms(5); if(CANL==0) { mode=0; Write_com(0x0c); break; } if(SET==0)break; } WriteSet1302(0x8e,0x80);}voidyearset(void) //调年{ unsignedchardatevalue,year; delay1ms(500);WriteSet1302(0x8e,0x00); datevalue=ReadSet1302(0x8d); year=(((datevalue&0x70)>>4)*10+(datevalue&0x0f)); while(1) { if(ADD==0) { delay1ms(10); if(ADD==0) { year++; while(ADD==0); } } if(RED==0) { delay1ms(10); if(RED==0) { year--; delay1ms(300); while(RED==0); } } datevalue=((year/10)<<4|(year%10)); WriteSet1302(0x8c,datevalue); delay1ms(5); display_Year(year); delay1ms(5); Write_Address(0x09); delay1ms(5); if(CANL==0) { mode=0; Write_com(0x0c); break; } if(SET==0)break; } WriteSet1302(0x8e,0x80);}voidmonthset(void) //调月{ unsignedchardatevalue,month;delay1ms(500); WriteSet1302(0x8e,0x00); datevalue=ReadSet1302(0x89); month=(((datevalue&0x70)>>4)*10+(datevalue&0x0f)); while(1) { if(ADD==0) { delay1ms(10); if(ADD==0) { month++; if(month>12)month=1; while(ADD==0); } } if(RED==0) { delay1ms(10); if(RED==0) { month--; delay1ms(300); if(month==0)month=12; while(RED==0); } } datevalue=((month/10)<<4|(month%10)); WriteSet1302(0x88,datevalue); delay1ms(1); display_Month(month); Write_Address(0x0c); delay1ms(5); if(CANL==0) { mode=0; Write_com(0x0c); break; } if(SET==0)break; } WriteSet1302(0x8e,0x80);}voiddayset(void) //调日{ unsignedchardatevalue,day; delay1ms(500); WriteSet1302(0x8e,0x00); datevalue=ReadSet1302(0x87); day=(((datevalue&0x70)>>4)*10+(datevalue&0x0f)); while(1) { if(ADD==0) { delay1ms(10); if(ADD==0) { day++; if(day>31)day=1; while(ADD==0); } } if(RED==0) { delay1ms(10); if(RED==0) { day--; delay1ms(300); if(day==0)day=31; while(RED==0); } } datevalue=((day/10)<<4|(day%10)); WriteSet1302(0x86,datevalue); delay1ms(1); display_Day(day); Write_Address(0x0f); delay1ms(5); if(CANL==0) { mode=0; Write_com(0x0c); break; } if(SET==0)break; } WriteSet1302(0x8e,0x80);}voidalarmhourset(void) //闹钟小时调整{ unsignedcharvalue; value=houra;while(1){ if(ADD==0) { delay1ms(20); if(ADD==0) { Write_com(0x0c); delay1ms(5); value++; if(value>23)value=0; while(ADD==0); } } if(RED==0) { delay1ms(20); if(RED==0) { value--; if(value==0)value=23; while(RED==0); } } houra=value; display_houra(houra); gbdisplay(0x45); if(CANL==0) { delay1ms(500); break; }}}voidalarmminuteset(void) //闹钟分钟调整{while(1){ if(ADD==0) { delay1ms(20); if(ADD==0) { minutea++; if(minutea>59)minutea=0; while(ADD==0); } } if(RED==0) { delay1ms(20); if(RED==0) { minutea--; if(minutea==0)minutea=59; while(RED==0); } } display_minutea(minutea); gbdisplay(0x48); if(CANL==0) { delay1ms(500); break; }}}voidTimeSet(void) //时间调整函数{ display_Time(); if(SET==0) { delay1ms(10); if(SET==0) { mode++; delay1ms(20); switch(mode) { case(1):{gbdisplay(0x48);hourset(); delay1ms(500);}break; case(2):{gbdisplay(0x4c);minuteset();delay1ms(500);}break; case(3):{gbdisplay(0x4f);secondset();delay1ms(500);}break; case(4):{gbdisplay(0x09);yearset();delay1ms(500);}break; case(5):{gbdisplay(0x0c);monthset();delay1ms(500);}break; case(6):{gbdisplay(0x0f);dayset();delay1ms(500);}break; } if(mode==7)mode=0; } }}/***************显示温度模块********************/unsignedcharcodedisplayexplain[]={"Digitthermometer"};unsignedcharcodedisplayerror[]={"DS18B20ERROR"};unsignedcharcodedisplayerror1[]={"PLEASECHECK"};unsignedcharcodedisplaypart1[]={"WenDu:"};unsignedcharcodedisplaypart2[]={"Cent"};unsignedcharflag;/**********************操作DS18B20模块***************************/sbitDQ=P3^3;unsignedchartime;/**********************DS18B20初始化****************************/bitIntDS18B20(void){ bittemp; DQ=1; for(time=0;time<2;time++); DQ=0; for(time=0;time<200;time++); DQ=1; for(time=0;time<10;time++); temp=DQ; for(time=0;time<200;time++); returntemp;}/**************************读DS18B20**********************/unsignedcharReadDS18B20(void){ unsignedchari; unsignedchardat; for(i=0;i<8;i++) { DQ=1; _nop_(); DQ=0; _nop_(); DQ=1; for(time=0;time<2;time++);dat>>=1; if(DQ==1) dat=dat|0x80; else dat=dat|0x00; for(time=0;time<10;time++); } returndat;}/*********************向DS18B20写数据**************************/voidWriteDS18B20(unsignedchardate){ unsignedchari; for(i=0;i<8;i++) { DQ=1; _nop_(); DQ=0; DQ=date&0x01; for(time=0;time<10;time++); DQ=1; for(time=0;time<1;time++); date>>=1; } for(time=0;time<4;time++);}/*******************为读取温度做好准备************************/voidReadyreadDS18B20(void){ IntDS18B20(); WriteDS18B20(0XCC); WriteDS18B20(0X44); delay1ms(200); IntDS18B20(); WriteDS18B20(0XCC); WriteDS18B20(0XBE); }/*************在1602液晶上显示相关信息模块**********************//****************当未检测到DS18B20时显示信息模块****************/voidDisplay_Error(void){ unsignedchari=0; Write_Address(0x00); while(displayerror[i]!='\0') { Write_Date(displayerror[i]); i++; delay1ms(100); } delay1ms(5); i=0; Write_Address(0x40); while(displayerror1[i]!='\0') { Write_Date(displayerror1[i]); i++; delay1ms(100); } delay1ms(3000);}/*************温度显示模块****************/voidDisplay_Explain(void){ unsignedchari=0; Write_Address(0x00); delay1ms(5); while(displayexplain[i]!='\0') { Write_Date(displayexplain[i]); i++; delay1ms(5); } i=0; Write_Address(0x40); while(displaypart1[i]!='\0') { Write_Date(displaypart1[i]); i++; delay1ms(5); } i=0; Write_Address(0x4C); while(displaypart2[i]!='\0') { Write_Date(displaypart2[i]); i++; delay1ms(5); } Write_Address(0x49); Write_Date('.'); delay1ms(5);}/*********************显示温度整数部分*************************/voidDisplay_Integer(unsignedcharx){ unsignedchari,j,k; i=x/100; j=x%100/10; k=x%10; Write_Address(0x46); if(flag==1)Write_Date('-'); Write_Date(digit[i]); Write_Date(digit[j]); Write_Date(digit[k]); delay1ms(50);}/************显示温度小数部分*********************/voidDisplay_Decimal(unsignedcharx){ Write_Address(0x4A); delay1ms(5); Write_Date(digit[x]); delay1ms(50);}voiddisplayovert(void){ unsignedchari; Write_com(0x01); delay1ms(10); Write_Address(0x03); delay1ms(10); Write_Date('W'); Write_Date('A'); Write_Date('R'); Write_Date('N'); Write_Date('I'); Write_Date('N'); Write_Date('G'); Write_Date('!'); Write_Address(0x40);while(overtemperature[i]!='\0') { Write_Date(overtemperature[i]); i++; delay1ms(10); }}/*******************温度主函数********************/voidTemperature(void){ unsignedchari; delay1ms(5); if(IntDS18B20()!=0) Display_Error(); else { delay1ms(1); Write_com(0x01); delay1ms(5); Display_Explain(); for(length=50;length>0;length--) { for(i=0;i<6;i++) { flag=0; ReadyreadDS18B20(); TL=ReadDS18B20(); TH=ReadDS18B20(); if((TH&0XF8)!=0X00) { flag=1; TL=~TL; TH=~TH; TL+=1; if(TL>255)TH+=1; TN=TH*16+TL/16; TD=(TL%16)*10/16; } TN=TH*16+TL/16; TD=(TL%16)*10/16; Display_Integer(TN); Display_Decimal(TD); delay1ms(10); } if(tempswitch==1){ if(TN>=Maxtemp) { Write_Address(0x03); delay1ms(5); displayovert(); while(1) { baojing(1); if(CANL==0) { Write_com(0x01); delay1ms(5); break; } } } } if(CANL==0)break; } }}voidtempset(void){ if(ADD==0) { delay1ms(10); if(ADD==0) { Maxtemp++; while(ADD==0); } } if(RED==0) { delay1ms(10); if(RED==0) { Maxtemp--; while(RED==0); } }}voidMaxtempset(void) //高温报警设置{ Write_com(0x01); delay1ms(10); Write_Address(0x03); delay1ms(10); Write_Date('T'); Write_Date('E'); Write_Date('M'); Write_Date('P'); Write_Address(0x09); Write_Date('S'); Write_Date('E'); Write_Date('T'); Write_Address(0x40); Write_Date('M'); Write_Date('A'); Write_Date('X'); Write_Date(':'); while(1) { if(SET==0) { delay1ms(20); if(SET==0) { Write_Address(0x4e); Write_com(0x0f); while(1) { if(ADD==0) { delay1ms(20); if(ADD==0) { Write_Address(0x4b); delay1ms(5); Write_Date('O'); Write_Date('N'); Write_Date(''); tempswitch=1; } } if(RED==0) { delay1ms(20); if(RED==0) { Write_Address(0x4b); Write_Date('O'); Write_Date('F'); Write_Date('F'); tempswitch=0; } } if(CANL==0) { delay1ms(500); break; } } } } if(tempswitch==1) { Write_Address(0x4b); Write_Date('O'); Write_Date('N'); Write_Date(''); tempset(); displaymaxt(Maxtemp); if(CANL==0) { Write_com(0x01); displaymainpart(); break; } } if(tempswitch==0) { Write_com(0x0c); Write_Address(0x4b); Write_Date('O'); Write_Date('F'); Write_Date('F'); } if(CANL==0) { Write_com(0x01);displaymainpart(); break; } }}voidalarmswitchset(void){ while(1) { if(ADD==0) { delay1ms(100); if(ADD==0) { alarmmode=1; Write_Address(0x4c); Write_Date('O'); Write_Date('N'); Write_Date(''); } } if(RED==0) { alarmmode=0; Write_Address(0x4c); Write_Date('O'); Write_Date('F'); Write_Date('F'); } if(CANL==0) { delay1ms(500); break; } }}/****************设置模块******************/voidSet(void){ if(SET==0) { delay1ms(10); if(SET==0) { Write_Address(0x40); Write_Date('T'

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论