目录
摘 要
电子时钟是一种广泛应用于现代社会的计时工具,它可以对年、月、日、时、分和秒等多个时间信息进行计时,并且越来越受到欢迎。采用1602液晶可以使数字电子时钟直观地显示时间信息,包括年、月、日、时、分、秒等,并且具有时间设置等功能。本设计是基于51系列单片机进行的电子时钟设计,具有显示时间、星期和时间设置等功能,同时采用1602液晶显示。在硬件制作和软件编程方面进行同步设计,其中硬件部分包括STC89C52单片机、液晶显示电路和按键调节电路。软件部分包括时间调整程序、液晶显示程序和中断服务程序,所有程序均采用高级C语言编写。最终,经过大量资料查询和指导老师的帮助,小组成功完成了电子时钟的设计和Protues仿真。
关键词 AT89C52; 电子钟; 单片机。
1.课程设计任务
1.1课程设计题目
1.2设计的要求
用控制器实现一个数字电子钟,具体要求如下。
设计要求:
(1)控制器可选用单片机、ARM 或可编程逻辑器件,显示器件和按键无限
制。
(2) 有基本的时间功能,可切换 24 小时制或 12 小时制显示。
(3)可设定日期(年月日,星期)。
(4)可设定 4 组以上的闹钟,掉电后不丢失。
发挥部分
(5)如何提高时钟的走时精度(一天的误差秒数)。
(6)尽量降低功耗,使用电池供电。
(7)有万年历功能,能通过互联网络自动校准时间。
2.设计总体方案
2.1初步设计方案
按照系统总体要求,用功能模块框图表达整体功能,如图1所示。
图1 功能模块框图
该系统由51单片机、时钟芯片、温度传感器、LCD液晶显示屏、按键、蜂鸣器等组成。其中,时钟芯片作为时钟模块,实现对时间的读取和设置;温度传感器,获取当前温度信息;LCD液晶显示屏用于显示时间和其他相关信息;按键用于对时钟进行设置和调整;蜂鸣器用于发出闹铃提示。
在该系统中,51单片机作为主控芯片,通过和时钟芯片的通信,实现对时间的读取和设置,通过温度传感器获取当前温度信息;并通过LCD液晶显示屏显示当前时间和温度;通过按键进行时钟的设置和调整;当闹铃时间到达时,蜂鸣器会发出提示声音。
2.2芯片的选型
2.2.1时钟芯片的选择
方案一:DS1302这是一款精度高、价格便宜、容易集成和编程的时钟芯片。它具有存储日历信息和时钟时间的能力,并提供可编程的时钟输出。
方案二:DS3231这是一款高精度、低功耗的时钟芯片,它的时钟精度可达到2ppm。它具有年、月、日、星期、时、分和秒等7种计时功能,支持两种闹钟设置。
方案三:PCF8583这是一款具有计时和定时功能的单芯片RTC时钟,适用于需要精确计时的应用。
2.2.2温度传感器的选择
方案一:DS18B20是一款数字温度传感器芯片,具有高精度、数字输出、可编程分辨率等特点。它采用单总线接口,可以通过单一数据线与微控制器通讯,体积小、使用方便。
方案二:LM35是一款精度高、输出线性、温度范围广的模拟温度传感器芯片,可以直接输出温度值,输出电压与温度成线性关系。
2.2.3显示电路的选择
方案一:采用四位共阳极数码管显示,动态扫描显示方式;
方案二:采用液晶显示屏LCD 显示。
2.2.4输入按键的选择
方案一:采用 4*4键盘;
方案二:采用 4*1按键;
2.2.5控制电路芯片的选择
方案一: 51 单片机;
2.3总体方案
设计要求的综合考虑是指在设计系统时,需要综合考虑各种因素,如功能要求、硬件成本、软件实现难度、系统性能等,以选定一个最优的总体方案。在该系统中,根据设计要求的综合考虑,选定的总体方案包括51单片机、DS1302时钟芯片、DS18B20温度传感器、LCD液晶显示屏、8*1按键和蜂鸣器等组件。
其中,DS1302时钟芯片作为时钟模块,通过单片机的SPI总线进行通信,实现对时间的读取和设置;DS18B20温度传感器通过单片机的单总线进行通信,获取当前温度信息。LCD液晶显示屏用于显示时间和其他相关信息。8*1按键用于对时钟进行设置和调整,提供了更加便捷的操作方式。而蜂鸣器则用于发出闹铃提示,增加了系统的实用性和用户体验。
作为主控芯片,51单片机通过和DS1302时钟芯片的通信,实现对时间的读取和设置,并通过DS18B20温度传感器获取当前温度信息。LCD液晶显示屏可以显示当前时间和温度,提高了系统的可视性和易用性。同时,按键可以进行时钟的设置和调整,让用户能够更加方便地对系统进行操作。当闹铃时间到达时,蜂鸣器会发出提示声音,提醒用户。
因此,该系统通过综合考虑各种因素,选定了最优的总体方案,实现了时钟、温度显示和闹铃提示等多种功能,提高了系统的可用性和用户体验。
3.单元模块设计
硬件电路的模块设计包括显示模块、按键模块、闹钟的蜂鸣器模块、DS1302时钟芯片模块、DS18B20温度传感器。
3.1显示模块
LCD1602是一种16字符×2行的液晶显示屏,它使用液晶技术来显示文本和图形。其工作原理是通过液晶分子的旋转来控制光的透过和反射,从而实现图像和文字的显示。LCD液晶显示屏通过并行接口或串行接口与主控芯片进行通信,以实现图像和文字的显示。
3.2按键模块
按键是一种常见的机械开关,其工作原理是当按键按下时,开关内部的触点短接,导通电路,从而传递按键事件到主控芯片中,实现对系统的设置和调整等功能。
3.3蜂鸣器模块
蜂鸣器是一种能够发出声音的电子元件,其工作原理是通过交替的电压信号来驱动蜂鸣器内部的振荡器,从而产生声音。在该系统中,蜂鸣器用于发出闹铃提示,增加了系统的实用性和用户体验。
3.4 DS1302时钟芯片模块
DS1302时钟芯片是一种实时时钟模块,其工作原理是通过一个晶体振荡器产生一个高频信号,然后通过分频电路将其分频为1Hz的信号,作为实时时钟的时钟源。该芯片还内置了时钟和日历计数器,并通过SPI总线与主控芯片通信,实现对时间的读取和设置。
3.5 DS18B20温度传感器
DS18B20温度传感器是一种数字温度传感器,其工作原理是基于热敏电阻效应。在DS18B20中,一个独特的ROM存储器存储了器件的唯一序列号,并与传感器的温度传感电路相连。当传感器测量温度时,温度值将被转换为数字信号,并通过单总线接口传输到主控芯片中。
图6 温度传感器图
4.软件流程图
软件是该系统的重要组成部分,在系统的软件设计中我们也才用了模块化设计,将系统的各部分功能编写成子模块的形式,这样增强了系统软件的可读性和可移植性。软件系统流程图见图8。
图8 软件流程图
时间设置、闹钟设置和温度显示是闹钟应用程序中三个重要的功能,它们可以被用户选择并独立运行。这些功能之间没有必要的先后顺序,用户可以按照自己的需要和喜好选择运行它们。
时间设置是闹钟应用程序中的一个核心功能,它允许用户设置所需的时间,例如小时和分钟。在程序内存中存储时间数据后,用户可以随时查看所设置的时间,并在必要时进行修改。
闹钟设置是另一个重要的功能,它允许用户设置多个闹钟。一旦设置完毕,程序将在预定时间响铃提醒用户。
温度显示是一个额外的功能,它可以帮助用户监测周围环境的温度。在这个模块中,程序从传感器获取环境温度,并将其显示在用户界面上。这个功能可以帮助用户了解周围环境的温度,以便做出更好的决策。
总之,时间设置、闹钟设置和温度显示是闹钟应用程序中的三个核心功能,用户可以根据需要和喜好选择运行它们。
5.系统电路设计
5.1整体电路
5.2仿真结果
5.2.1有基本的时间功能,可切换 24 小时制或 12 小时制显示
图8 仿真结果一
5.2.2可设定日期(年月日,星期)
在该系统中,设定日期是一个重要的功能,它通过定时器0中断工作方式1来实现。定时器0是单片机中常用的计时器之一,它可以在定时器计数器计数到设定值时触发一个中断。这种中断方式可以使单片机能够精确计时,并且在一定程度上减少了单片机对CPU的占用率。
在设定日期时,系统使用定时器0中断工作方式1来实现闪烁功能。闪烁是一种使指定位以一定频次快速闪烁的效果,可以提醒用户该位正在进行设置。在该系统中,设定位以500ms频次闪烁来进行设置,这意味着该位会以每隔500ms的频率闪烁一次,提醒用户该位正在进行设置。
通过定时器0中断工作方式1,系统可以精确地控制闪烁的频率,并且可以在单片机计算其他操作时同时完成设定日期的功能,提高了系统的效率。因此,该系统的设计合理,实现了较为稳定和可靠的日期设定功能。
图9 仿真结果二
5.2.3可设定 4 组以上的闹钟,掉电后不丢失
在使用闹钟时,我们需要按下闹钟按键来设置闹钟时间。这是一个必要的步骤,因为只有设置好时间,闹钟才能在预定时间响起。一旦我们完成了时间的设置,我们就可以按下闹钟标志按键来开启闹钟。这个按键的作用是告诉闹钟设备,在预定时间响起闹铃。通过这样的设置,我们可以在需要的时间受到提醒,从而更好地规划时间并完成任务。因此,按下闹钟按键并设置好时间,然后按下闹钟标志按键,是使用闹钟的两个关键步骤。
图10 仿真结果三
6.系统调试
6.1ds1302读取系统时间出现问题
DS1302是一款实时时钟芯片,通常用于单片机等嵌入式系统中。在读取系统时间时遇到问题存在以下几种可能:
(1)DS1302芯片未正确连接到系统中,需要检查硬件电路连接是否正确,包括引脚、电源等连接是否正常。
(2)DS1302芯片未正确配置,需要检查芯片寄存器的配置是否正确,例如时钟频率、读写模式等。
(3)软件程序中读取DS1302芯片的时间方式不正确,需要检查程序中的代码是否正确。例如,读取时间时需要先发送读取命令,并等待芯片响应后再读取时间数据。
(4)系统中存在其他影响DS1302读取时间的问题,例如电源电压不稳定等问题。
6.2修改调整的方法
为了解决DS1302读取系统时间的问题,可以采取以下方法:
(1)检查硬件连接是否正确,包括引脚、电源等连接是否正常。
(2)检查芯片寄存器的配置是否正确,包括时钟频率、读写模式等设置是否正确。
(3)检查软件程序中读取DS1302芯片的时间方式是否正确,需要仔细检查程序代码,特别是读取时间的代码部分。
(4)如有必要,可以通过示波器等工具检测DS1302芯片的输出信号,以确定是否存在硬件连接或配置问题。
6.3系统设计总结
硬件设计:51单片机电子钟的硬件设计包括主频选取、时钟电路、LCD液晶显示屏、按键、温度传感器、蜂鸣器等。其中,时钟电路是实现电子钟功能的核心,通常采用DS1302时钟芯片,可精准地获取当前时间并进行显示。温度传感器可以实时监测当前环境温度,以便于显示室内温度。同时,蜂鸣器也是电子钟的必备组件之一,可用于闹钟提示等功能。
软件设计:51单片机电子钟的软件设计包括时钟芯片驱动程序、LCD液晶显示程序、按键扫描程序、温度采集程序等。其中,时钟芯片驱动程序是实现时钟功能的核心,通过读取DS1302时钟芯片的寄存器来获取时间信息并进行显示。LCD液晶显示程序主要用于实现对当前时间和室内温度的显示。按键扫描程序用于检测按键是否被按下,并对按键进行相应的处理。温度采集程序则用于实时采集温度传感器的温度数据并进行显示。
整体设计:51单片机电子钟的整体设计需要充分考虑硬件和软件的配合,以确保系统的稳定性和可靠性。在实现功能的同时,还需要注意到系统的实用性,例如合理布局显示屏幕的显示内容,便于用户阅读。同时还需要注意到电子钟的精度和稳定性,应定期进行时间校准和温度校准。
总之,51单片机电子钟设计需要充分考虑硬件和软件的设计,并进行整体优化。通过合理的设计和优化,可以实现功能完备、稳定可靠的电子钟系统。
7.总结
7.1心得体会
在此次的课程设计中,我深刻认识到自身在编程和调试方面的不足,发现自己所学的知识还有很多需要补充和提高。经过资料的收集和文件的检索,我找到了解决问题的方法,顺利完成了此次课程设计的任务。通过实践,我不仅学到了许多新的知识,还深化了课堂上学到的理论,并增强了自己将理论与实际结合的操作能力。在这个过程中,我获得了宝贵的经验,例如理论必须与实践相结合才能得以应用,知识必须通过实践才能实现其价值。此外,我还提高了自己的动手能力,为今后的学习和工作奠定了良好的基础。
7.2系统的优缺点
该系统的组成使用了多种元件,包括51单片机、DS1302时钟芯片、DS18B20温度传感器、LCD液晶显示屏、8*1按键和蜂鸣器。其优缺点如下:
优点:
(1)高精度:DS1302时钟芯片具有高精度的计时功能,可以确保电子钟的时间准确性。
(2)多功能:除了显示时间之外,还可以显示室内温度,并且可以通过按键设置闹钟功能等,功能较为全面。
(3)显示效果好:使用LCD液晶显示屏,可以显示清晰、鲜艳的数字,同时可以调节亮度,适应不同环境。
(4)操作简便:使用8*1按键,可以方便地进行时间、闹钟等设置操作。
缺点:
(1)复杂度高:该数字电子钟的设计较为复杂,需要使用多种元件,需要对这些元件的使用方法和接线有一定的了解。
(2)成本较高:由于使用了多种元件,所以成本相对较高。
(3)维护困难:如果其中某个元件出现故障,维修和更换难度较大。
总的来说,该数字电子钟的优点在于功能多、显示效果好、操作简便等方面,但同时也存在复杂度高、成本高等缺点。如果在设计时考虑到这些缺点,可以在使用过程中更好地避免和解决相关问题。
7.3设计的改进思路
在该系统的按键检测中,采用了while循环等待按键状态改变,这种方式容易导致死循环问题。当按键一直处于相同状态时,程序就会一直在while循环中等待,无法进行其他操作,导致程序停止响应。
为了解决这个问题,可以采用以下改进思路:
(1)使用定时器中断检测按键状态:使用定时器中断来周期性地检测按键状态,这种方式可以有效避免死循环等待问题,提高程序的响应速度。
(2)使用状态机设计按键检测:采用状态机的方式来设计按键检测程序,通过检测按键状态的变化来切换状态机的状态,从而避免死循环等待问题。
(3)使用中断检测按键状态:使用外部中断或者内部中断来检测按键状态的变化,这种方式可以在按键状态改变时立即进行响应,避免死循环等待问题。
(4)使用其他方法检测按键状态:例如采用电容触摸按键、红外线接收等方式来检测按键状态,这种方式可以避免使用传统按键开关带来的死循环等待问题。
总之,在单片机的按键检测中,需要注意避免死循环等待问题,采用合适的检测方式来确保程序的响应速度和稳定性。
参考文献
[1]张晔,等.单片机应用技术[M].北京:高等教育出版社,2006,6.
[2]谭家玉,郑大宇,等.单片机原理及接口技术[M].哈尔滨:哈尔滨工业大学出版社,2003,5.
[3]周凤娥, 闫祖霞. 基于51单片机的数字电子钟的设计与实现[J]. 计算机与数字工程, 2019, 47(10): 205-206.
[4]李海峰, 任杰. 基于51单片机的数字电子钟的设计与实现[J]. 计算机与数字工程, 2018, 46(11): 184-186.
[5]王传博, 王威. 基于单片机的风力发电机控制系统的研究与设计[J]. 机电工程, 2019, 36(2):69-72.
[6]陈建强, 王志豪, 魏锋. 基于单片机的消防报警系统的设计与实现[J]. 消防科学与技术, 2019, 38(6):98-101.
[7]王荣华, 李想. 基于单片机的自动化化学分析仪的研究与设计[J]. 化学教育, 2019, 40(6):49-51.
[8]朱德杰, 陈鹏. 基于单片机的航空监控系统的研究与设计[J]. 航空制导技术, 2019, 38(3):78-82.
[9]李光辉, 赵淑贤. 基于单片机的自动售货机控制系统的研究与设计[J]. 电脑知识与技术, 2019, 15(14):48-51.
[10]张维, 杨强. 基于单片机的工业自动化系统设计与应用[J]. 机械科学与技术, 2019, 38(6):108-112.
附件
#include <REGX52.H> #include "LCD1602.h" #include "DS1302.h" #include "Key.h" #include "Timer0.h" #include "Delay.h" #include "DS18B20.h" unsigned char i,KeyNum,MODE,TimeSetSelect,TimeSetFlashFlag; unsigned char bell_data1[6]={0,0,0,20,30,0}; unsigned char bell_data2[6]={0,0,0,20,30,0}; unsigned char bell_data3[6]={0,0,0,20,30,0}; unsigned char bell_data4[6]={0,0,0,20,30,0}; unsigned char bell_flag=0; //闹钟功能开关 unsigned char bell_onoff=0; //闹钟开关 float T; sbit BEEP=P2^2;//蜂鸣器 void TimeShow(unsigned char *time)//时间显示功能 { DS1302_ReadTime();//读取时间 LCD_ShowNum(1,1,time[0],2);//显示年 LCD_ShowNum(1,4,time[1],2);//显示月 LCD_ShowNum(1,7,time[2],2);//显示日 LCD_ShowNum(2,1,time[3],2);//显示时 LCD_ShowNum(2,4,time[4],2);//显示分 LCD_ShowNum(2,7,time[5],2);//显示秒 LCD_ShowNum(1,10,time[6],1);//显示星期 } void TimeSet(void)//时间设置功能 { // Timer0Init(); if(KeyNum==2)//按键2按下 { TimeSetSelect++;//设置选择位加1 TimeSetSelect%=7;//越界清零 } if(KeyNum==3)//按键3按下 { DS1302_Time[TimeSetSelect]++;//时间设置位数值加1 if(DS1302_Time[0]>99){DS1302_Time[0]=0;}//年越界判断 if(DS1302_Time[1]>12){DS1302_Time[1]=1;}//月越界判断 if( DS1302_Time[1]==1 || DS1302_Time[1]==3 || DS1302_Time[1]==5 || DS1302_Time[1]==7 || DS1302_Time[1]==8 || DS1302_Time[1]==10 || DS1302_Time[1]==12)//日越界判断 { if(DS1302_Time[2]>31){DS1302_Time[2]=1;}//大月 } else if(DS1302_Time[1]==4 || DS1302_Time[1]==6 || DS1302_Time[1]==9 || DS1302_Time[1]==11) { if(DS1302_Time[2]>30){DS1302_Time[2]=1;}//小月 } else if(DS1302_Time[1]==2) { if(DS1302_Time[0]%4==0) { if(DS1302_Time[2]>29){DS1302_Time[2]=1;}//闰年2月 } else { if(DS1302_Time[2]>28){DS1302_Time[2]=1;}//平年2月 } } if(DS1302_Time[3]>23){DS1302_Time[3]=0;}//时越界判断 if(DS1302_Time[4]>59){DS1302_Time[4]=0;}//分越界判断 if(DS1302_Time[5]>59){DS1302_Time[5]=0;}//秒越界判断 if(DS1302_Time[6]>7){DS1302_Time[6]=1;}//星期越界判断 } if(KeyNum==4)//按键3按下 { DS1302_Time[TimeSetSelect]--;//时间设置位数值减1 if(DS1302_Time[0]<0){DS1302_Time[0]=99;}//年越界判断 if(DS1302_Time[1]<1){DS1302_Time[1]=12;}//月越界判断 if( DS1302_Time[1]==1 || DS1302_Time[1]==3 || DS1302_Time[1]==5 || DS1302_Time[1]==7 || DS1302_Time[1]==8 || DS1302_Time[1]==10 || DS1302_Time[1]==12)//日越界判断 { if(DS1302_Time[2]<1){DS1302_Time[2]=31;}//大月 if(DS1302_Time[2]>31){DS1302_Time[2]=1;} } else if(DS1302_Time[1]==4 || DS1302_Time[1]==6 || DS1302_Time[1]==9 || DS1302_Time[1]==11) { if(DS1302_Time[2]<1){DS1302_Time[2]=30;}//小月 if(DS1302_Time[2]>30){DS1302_Time[2]=1;} } else if(DS1302_Time[1]==2) { if(DS1302_Time[0]%4==0) { if(DS1302_Time[2]<1){DS1302_Time[2]=29;}//闰年2月 if(DS1302_Time[2]>29){DS1302_Time[2]=1;} } else { if(DS1302_Time[2]<1){DS1302_Time[2]=28;}//平年2月 if(DS1302_Time[2]>28){DS1302_Time[2]=1;} } } if(DS1302_Time[3]<0){DS1302_Time[3]=23;}//时越界判断 if(DS1302_Time[4]<0){DS1302_Time[4]=59;}//分越界判断 if(DS1302_Time[5]<0){DS1302_Time[5]=59;}//秒越界判断 if(DS1302_Time[6]<1){DS1302_Time[6]=7;}//星期越界判断 } //更新显示,根据TimeSetSelect和TimeSetFlashFlag判断可完成闪烁功能 if(TimeSetSelect==0 && TimeSetFlashFlag==1){LCD_ShowString(1,1," ");} else {LCD_ShowNum(1,1,DS1302_Time[0],2);} if(TimeSetSelect==1 && TimeSetFlashFlag==1){LCD_ShowString(1,4," ");} else {LCD_ShowNum(1,4,DS1302_Time[1],2);} if(TimeSetSelect==2 && TimeSetFlashFlag==1){LCD_ShowString(1,7," ");} else {LCD_ShowNum(1,7,DS1302_Time[2],2);} if(TimeSetSelect==3 && TimeSetFlashFlag==1){LCD_ShowString(2,1," ");} else {LCD_ShowNum(2,1,DS1302_Time[3],2);} if(TimeSetSelect==4 && TimeSetFlashFlag==1){LCD_ShowString(2,4," ");} else {LCD_ShowNum(2,4,DS1302_Time[4],2);} if(TimeSetSelect==5 && TimeSetFlashFlag==1){LCD_ShowString(2,7," ");} else {LCD_ShowNum(2,7,DS1302_Time[5],2);} if(TimeSetSelect==6 && TimeSetFlashFlag==1){LCD_ShowString(1,10," ");} else {LCD_ShowNum(1,10,DS1302_Time[6],1);} } void main() { unsigned char set_bell=0; unsigned char set_shift_bell=0; LCD_Init(); DS1302_Init(); Timer0Init(); LCD_ShowString(1,1," - - ");//静态字符初始化显示 LCD_ShowString(2,1," : : "); // DS1302_SetTime(DS1302_Time);//设置时间 DS1302_ReadTime(); DS1302_SetTime(DS1302_Time);//设置时间 DS18B20_ConvertT(); //上电先转换一次温度,防止第一次读数据错误 Delay(100); //等待转换完成 while(1) { DS18B20_ConvertT(); //转换温度 T=DS18B20_ReadT(); //读取温度 KeyNum=Key();//读取键码 if(KeyNum==1)//按键1按下 { if(MODE==0){MODE=1;TimeSetSelect=0;}//功能切换 else if(MODE==1){MODE=0;DS1302_SetTime(DS1302_Time);} } switch(MODE)//根据不同的功能执行不同的函数 { case 0:TimeShow(DS1302_Time);break; case 1:TimeSet();break; } switch(KeyNum) { case 2: bell_onoff=0;BEEP=1; break;//¹Ø±ÕÄÖÁ case 3: if(T<0) //如果温度小于0 { LCD_ShowChar(1,12,'-'); //显示负号 T=-T; //将温度变为正数 } else //如果温度大于等于0 { LCD_ShowChar(1,12,'+'); //显示正号 } LCD_ShowNum(1,13,T,2); //显示温度整数部分 LCD_ShowChar(1,15,'.'); //显示小数点 LCD_ShowNum(1,16,(unsigned int)(T*10)%10,1);//显示温度小数部分 break; case 5: set_bell=1; TimeShow(bell_data1); while(set_bell) { TimeShow(bell_data1); Delay(50);Delay(50);Delay(50); KeyNum=Key(); switch(KeyNum) { case 1: bell_flag=!bell_flag; if(bell_flag)LCD_ShowNum(2,10,1,1); else LCD_ShowNum(2,10,0,1); break; case 2: if(set_shift_bell++>0)set_shift_bell=0;break; case 5: TimeShow(bell_data1);set_bell=0;break; case 3: bell_data1[4-set_shift_bell]++;break; case 4: bell_data1[4-set_shift_bell]--;break; default : break; } } break; case 6: set_bell=1; TimeShow(bell_data2); while(set_bell) { TimeShow(bell_data2); Delay(50);Delay(50);Delay(50); KeyNum=Key(); switch(KeyNum) { case 1: bell_flag=!bell_flag; if(bell_flag)LCD_ShowNum(2,11,2,1); else LCD_ShowNum(2,11,0,1); break; case 2: if(set_shift_bell++>0)set_shift_bell=0;break; case 6: TimeShow(bell_data2);set_bell=0;break; case 3: bell_data2[4-set_shift_bell]++;break; case 4: bell_data2[4-set_shift_bell]--;break; default : break; } } break; case 7: set_bell=1; TimeShow(bell_data3); while(set_bell) { TimeShow(bell_data3); Delay(50);Delay(50);Delay(50); KeyNum=Key(); switch(KeyNum) { case 1: bell_flag=!bell_flag; if(bell_flag)LCD_ShowNum(2,12,3,1); else LCD_ShowNum(2,12,0,1); break; case 2: if(set_shift_bell++>0)set_shift_bell=0;break; case 7: TimeShow(bell_data3);set_bell=0;break; case 3: bell_data3[4-set_shift_bell]++;break; case 4: bell_data3[4-set_shift_bell]--;break; default : break; } } break; case 8: set_bell=1; TimeShow(bell_data4); while(set_bell) { TimeShow(bell_data4); Delay(50);Delay(50);Delay(50); KeyNum=Key(); switch(KeyNum) { case 1: bell_flag=!bell_flag; if(bell_flag)LCD_ShowNum(2,13,4,1); else LCD_ShowNum(2,13,0,1); break; case 2: if(set_shift_bell++>0)set_shift_bell=0;break; case 8: TimeShow(bell_data4);set_bell=0;break; case 3: bell_data4[4-set_shift_bell]++;break; case 4: bell_data4[4-set_shift_bell]--;break; default : break; } } break; default : break; }; if((bell_data1[3]==DS1302_Time[3] && bell_data1[4]==DS1302_Time[4] && bell_data1[5]==DS1302_Time[5])|| (bell_data2[3]==DS1302_Time[3] && bell_data2[4]==DS1302_Time[4] && bell_data2[5]==DS1302_Time[5])|| (bell_data3[3]==DS1302_Time[3] && bell_data3[4]==DS1302_Time[4] && bell_data3[5]==DS1302_Time[5])|| (bell_data4[3]==DS1302_Time[3] && bell_data4[4]==DS1302_Time[4] && bell_data4[5]==DS1302_Time[5])) { bell_onoff=1; } if(bell_flag && bell_onoff) { BEEP=!BEEP; } void Timer0_Routine() interrupt 1 { static unsigned int T0Count; TL0 = 0x18; //设置定时初值 TH0 = 0xFC; //设置定时初值 T0Count++; if(T0Count>=500)//每500ms进入一次 { T0Count=0; TimeSetFlashFlag=!TimeSetFlashFlag;//闪烁标志位取反 } }