多功能时钟(AVR)含完整程序
- 格式:doc
- 大小:323.50 KB
- 文档页数:26
多功能数字钟设计摘要:本系统基于Mega16设计,使用DS1302时钟芯片,通过LCD1602显示年月日、星期、时分秒,实现了计时与时间校正,正点报时与音乐闹钟,时钟掉电保持,日历和光标定位调整等功能。
关键词:AVR、Mega16、DS1302、LCD1602设计课题一多功能数字钟设计一、设计任务设计并制作一多功能数字钟二、设计要求1.基本要求(1)能实现基本的计时功能,采用24小时制计时,能在数码管或液晶上正常显示时、分、秒。
(2)时间校正功能; 时分均有校时功能。
(3)正点报时功能。
当计时器运行到59分49秒开始报时,每鸣叫1s就停叫1s,共鸣叫6,前5响为低音,频率为750Hz;最后1响为高音,频率为1KHz。
(4)可设定至少2个闹钟时间,当按下闹铃开关时,可在规定时间闹铃,当开关复位时,闹铃停止。
(5)时钟掉电保持功能,当电源掉电时时钟不停止。
2.发挥部分(1)增加日历功能,能正确显示年月日星期等。
(2)增加音乐闹钟功能。
(3)按键语音报时功能。
(4)无线遥控时钟功能。
(5)触摸报时功能。
(6)其它功能。
1 方案论证与比较1.1核心芯片方案一:选用ARM优点:自带实时时钟,速度快缺点:没有掉电时间保持功能,成本高方案二:选用mega16+DS1302优点:价格便宜,能满足课题的要求缺点:速度比ARM慢,需要另配时钟芯片芯片选择:两者价格相差比较大,价格便宜的mega16已经能满足课题设计的要求,所以选择方案二性价比高。
1.2显示模块方案一:数码管优点:价格便宜缺点:只能显示阿拉伯数字,需要大量的数码管,电路设计的复杂性高方案二:选用LCD1602优点:可以显示英文、数字和符号,屏幕显示细腻直观缺点:价格比数码管高显示选择:如果用数码管显示,至少需要17位数码管,成本也不低了,结合1602 的优点,所以选择方案二2 系统框图3 原理图正点报时按键控制模块蜂鸣器Mega16单片机DS1302时钟芯片音乐闹钟后备电池LCD1602 光标定位调整日历时间4、实现的功能:4.1计时功能4.2校正功能:年月日时分秒校正4.3正点报时功能4.4闹钟:多闹钟,开闹钟时显示ON,关闹钟显示OFF,闹钟响时可以关闭闹钟4.5时钟掉电保持功能4.6日历功能4.7音乐闹钟:音乐选择功能,《我和你》、《铃儿响叮当》供选择4.8光标定位调整:通过光标闪烁定位,关闭光标5 部分功能的介绍:5.1蜂鸣器部分CTC模式PD4\PD5输出方波和弦铃声整点报时铃声当需要750HZ 时,OCRnA=5332,当需要1000HZ 时,OCRnA=3999。
音乐闹钟的原理同上。
5.2、1602的光标定位调整能通过按键2在计时可以在年月日、星期、时分秒跳转,在设置闹钟时在时、分跳转,此时可以通过按键3修改或者设置。
当跳转一周时光标能消失。
5.3、闹钟关停开闹钟时显示ON,关闹钟显示OFF,闹钟响时可以关闭闹钟4.4时间/闹钟切换功能能够在显示实时时间画面与闹钟设置画面间切换。
6 测试结果和总结首先通过ISIS仿真,能用DS1302实现计时,通过LCD1602显示时间和日历,然后焊接电路,经过反复调试,该多功能数字钟工作稳定,时间精确度在允许的误差范围,整点报时声音清晰,音乐闹钟悦耳,基本满足设计的要求和发挥部分的一些功能。
经过本次的设计,对A VR的使用有了更深的了解,设计中还有一些欠缺的方面,在今后的学习中会努力改进。
7 使用手册使用手册:按键功能1 时间/闹钟切换2 光标调整定位/关光标3 加14 打开/关闭闹钟8 附录7、1附上全部程序#include <iom16v.h> //包含型号头文件#include <macros.h> //包含"位"操作头文件#define uchar unsigned char#define uint unsigned intuint p=1;int o=0;int u=0;int w=0;uint num=1;uint num1=1;uchar flag=0 ;uchar flag1 ;uchar key1;uchar a ;uchar b ;uchar c ;uchar d ;uchar e ;uchar f ;uchar g ;uchar gettime[7];uchar clock[7]={0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,};uchar clock2[]={1};uchar time11[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,};uint music_data1[]={587,698,466,523,587,349,466,523,587,698,523,587,698,466,523,587,392,523,349,523,587,466,784,698,784,466,587,392,587,698,523,587,698,466,523,587,392,523,349,523,587,466,0};uint music_data2[]={800,800,1600,800,800,1600,800,800,800,800,3200,800,800,1600,800,800,1600,800,800,800,800,1600,1600,1600,1600,1600,800,800,1200,400,3200,800,800,1600,800,800,1600,800,800,800,800,800,0};uchar guangbiao[]={8,5,11,8,13,5};#define TRUE 1#define FALSE 0#include "YJ1602.C" //包含1602液晶函数文件/******************RTC常量******************/#define RTC_CLK PB7#define RTC_DATA PB5#define RTC_CS PC7//命令#define RD 0x01#define WR 0x00#define C_SEC 0x80 //秒#define C_MIN 0x82 //分#define C_HR 0x84 //时#define C_DAY 0x86 //日#define C_MTH 0x88 //月#define C_WK 0x8A //星期DATE#define C_YR 0x8C //年#define C_WP 0x8E //控制(写保护)#define C_CHARGE 0x90 //涓流充电#define C_BURST 0xBE //时钟多字节//配置#define CLK_HALT 0x80 //停止时钟控制位SECOND bit7#define CLK_START 0x00 //启动时钟#define M12_24 0x80 //12/24小时值选择位HOUR bit7#define PROTECT 0x80 //写保护控制位CONTROL bit7#define UPROTECT 0x00 //写保护控制位CONTROL bit7 //涓流充电控制常量#define TC_D1R2 0xA5 //high 1 Diode +2K Resistors#define TC_D2R8 0xAB //low 2 Diodes+8K Resistors#define TC_DISABLED 0x00 //Disabled(TCS<>1010 or DS=00 or RS=00) //RAM 命令#define C_RAMBASE 0xC0 //RAM0~RAM30<<1 地址需左移一位void Delayus(uint US){uint i;US=US*5/4; //5/4是在8MHz晶振下,通过软件仿真反复实验得到的数值for( i=0;i<US;i++);}void Delayms(uint MS){uint i,j;for( i=0;i<MS;i++)for(j=0;j<1141;j++); //1141是在8MHz晶振下,通过软件仿真反复实验得到的数值}void yinyuenaozhong(uint j,uint k){DDRD|=0X30;for(j=0,k=0;j<43;j++,k++){if (flag1){guan();break;}else{TCCR1A=0X50;TCCR1B=0X09;OCR1A=jisuan(music_data1[j]);Delayms(music_data2[k]);TCCR1B = 0x00;}}TCCR1B = 0x00;}//频率转化uint jisuan(uint a){return 4000000/a-1;}/******************************************* 函数名称: DS1302_init功能: 初始化DS1302的数据接口参数: 无返回值: 无/********************************************/void DS1302_portinit(void){DDRB|=BIT(RTC_CLK)|BIT(RTC_DATA);//将时钟端(RTC_CLK)数据端(RTC_DATA)片选端(RTC_CS)设置为输出DDRC|=BIT(RTC_CS);}/*******************************************函数名称: DS1302_writeB功能: 向DS1302写入一个字节数据(没有RST操作)参数: byte--要写入的数据返回值: 无/********************************************/void DS1302_writeB(uchar byte){uchar i;for(i=0;i<8;i++) //8位数据计数{PORTB&=~BIT(RTC_CLK); //拉低时钟端if(byte&0x01) //当前位是否是1{PORTB|=BIT(RTC_DATA); //当前位是1,拉高数据端}else{PORTB&=~BIT(RTC_DATA); //当前位是0,拉低数据端}Delayus(10); //调整时钟和脉冲宽度PORTB|=BIT(RTC_CLK); //时钟上升沿(DS1302采样数据)byte>>=1; //数据右移1位,为送出新数据位做准备}}/*******************************************函数名称: DS1302_readB功能: 从DS1302读出一个字节数据(没有RST操作)参数: 无返回值: byte--读出的数据/********************************************/uchar DS1302_readB(void){uchar i,byte=0;DDRB&=~BIT(RTC_DATA); //将数据端口设置为输入PORTB&=~BIT(RTC_DATA); //无上拉电阻for(i=0;i<8;i++) //8位数据计数{byte>>=1; //保存读入的数据位PORTB|=BIT(RTC_CLK); //时钟上升沿Delayus(10); //延时,调整时钟脉冲宽度PORTB&=~BIT(RTC_CLK); //时钟下降沿,DS1302输出数据位Delayus(10); //等待数据变化(MEGA16太快,必须等待DS1302的数据位输出,否则不能正确读出)if(PINB&BIT(RTC_DA TA)) //当前位是否是高电平{byte|=BIT(PB7); //是高电平就将返回数据的当前位置1}else{byte&=~BIT(PB7); //是低电平就将返回数据的当前位置0}}DDRB|=BIT(RTC_DATA); //最后将数据端口设置为输出return byte; //返回读出的数据}/*******************************************函数名称: DS1302_writeD功能: 向DS1302的某个地址写入一个字节数据参数: addr--地址值(寄存器或RAM)data--要写入的地址返回值: 无/********************************************/void DS1302_writeD(uchar addr,uchar data){PORTC&=~BIT(RTC_CS); //拉低片选端PORTB&=~BIT(RTC_CLK); //拉低时钟端Delayus(10);PORTC|=BIT(RTC_CS); //拉高片选端Delayus(10); //调整片选脉冲DS1302_writeB(addr); //写入操作命令(地址)Delayus(10);PORTB&=~BIT(RTC_CLK); //拉低时钟端Delayus(10);DS1302_writeB(data); //写入数据PORTB&=~BIT(RTC_CLK); //拉低时钟端Delayus(10); //调整片选脉冲PORTC&=~BIT(RTC_CS); //拉低片选端}/*******************************************函数名称: DS1302_readD功能: 从DS1302的某个地址读出一个字节数据参数: addr--地址值(寄存器或RAM)返回值: data--读出的数据/********************************************/uchar DS1302_readD(uchar addr){uchar data;PORTC&=~BIT(RTC_CS); //拉低片选端PORTB&=~BIT(RTC_CLK); //拉低时钟端Delayus(10);PORTC|=BIT(RTC_CS); //拉高片选端Delayus(10); //调整片选脉冲DS1302_writeB(addr); //写入操作命令(地址)Delayus(10);data=DS1302_readB(); //读出数据Delayus(10);PORTB&=~BIT(RTC_CLK); //拉低时钟端PORTC&=~BIT(RTC_CS); //拉低片选端return data; //返回读出的数据}/*******************************************函数名称: DS1302_setT功能: 设置DS1302的时间参数: ptTimeD--设置时间数组指针返回值: 无/********************************************/void DS1302_setT(uchar ptTimeD[]){uchar i;uchar addr = 0x80; //写入地址从秒寄存器开始DS1302_writeD(C_WP|WR,UPROTECT); //控制命令,WP位为0,允许写操作Delayms(5);for(i=0;i<7;i++){DS1302_writeD(addr|WR,ptTimeD[i]); // 秒分时日月星期年addr+=2;Delayms(1);}DS1302_writeD(C_WP|WR,PROTECT); //控制命令,WP位为1,不允许写操作}/*******************************************函数名称: DS1302_getT功能: 读取DS1302的当前时间参数: time[]--读取的时间数组返回值: 无/********************************************/void DS1302_getT(uchar time[]){uchar i;////////下面的是单次读写///////////////////////////* uchar addr = 0x80; //读取地址从秒寄存器开始for(i=0;i<7;i++){time[i]=DS1302_readD(addr|RD); // 秒分时日月星期年addr+=2;}*//////////////////////////////////////////////////////////////下面是多字节读取///////////////PORTC&=~BIT(RTC_CS); //拉低片选端Delayus(10);PORTC|=BIT(RTC_CS); //拉高片选端Delayus(10); //调整片选脉冲DS1302_writeB(0xbf); // 0xbf:时钟多字节读取命令for (i=0;i<8;i++) //时间数据的存放格式是:{ //秒,分,时,日,月,星期,年,控制time[i]=DS1302_readB(); //【7个数据(BCD格式)+1个控制】}PORTC&=~BIT(RTC_CS); //拉低片选端///////////////////////////////////////////////PORTB&=~BIT(RTC_CLK); //拉低时钟端(时钟端在不操作时为低)}/*******************************************函数名称: DS1302_check功能: 检测DS1302是否正常工作参数: 无返回值: exist--为TRUE为检测到DS1302,为FALSE为没检测到/********************************************/uchar DS1302_check(void){uchar exist;DS1302_writeD(C_WP|WR,UPROTECT); //写入写允许命令DS1302_writeD(C_RAMBASE|WR,0xA5); //RAM0写入0xA5exist=DS1302_readD(C_RAMBASE|RD); //读取RAM0if(exist==0xA5){exist=TRUE; //如果读取值与写入值相等,返回TRUE }else{exist=FALSE; //如果读取值与写入值不相等,返回FALSE}return exist;}/*******************************************函数名称: DS1302_init功能: 初始化DS1302参数: 无返回值: 无/********************************************/void DS1302_init(void){DS1302_writeD(C_WP|WR,UPROTECT); //写入写允许命令DS1302_writeD(C_SEC|WR,CLK_START); //启动振荡器,DS1302开始工作DS1302_writeD(C_WP|WR,PROTECT); //控制命令,WP位为1,不允许写操作}/*******************************************函数名称: BCD_ASCII功能: 将压缩BCD码转换成ascii码参数: BCD--将要转换的压缩BCD码ptasc--转换后的ASCII码数组指针返回值: 无/********************************************/void BCD_ASCII(uchar BCD,uchar ptasc[]){ptasc[0]=BCD/16|0x30; //0X58 35 38 //转换十位ptasc[1]=BCD&0x0F|0x30; //转换个位}/*******************************************函数名称: Disp_time功能: 在1602液晶上显示当前时间(第1行格式:年-月-日星期;第2行格式:时-分-秒)参数: time[]--时间数组返回值: 无/********************************************/void Disp_time(uchar time[]){uchar i,asc[2];uchar line1[11]={0,0,'-',0,0,'-',0,0,' ',0,'\0'};//显示第1行的字符数组uchar line2[9]={0,0,':',0,0,':',0,0,'\0'}; //显示第2行的字符数组for(i=0;i<3;i++) //为第2行的字符数组赋值{BCD_ASCII(time[2-i],asc);line2[i*3]=asc[0];line2[i*3+1]=asc[1];}BCD_ASCII(time[6],asc); //为第1行的年赋值line1[0]=asc[0];line1[1]=asc[1];BCD_ASCII(time[4],asc); //为第1行的月赋值line1[3]=asc[0];line1[4]=asc[1];BCD_ASCII(time[3],asc); //为第1行的日赋值line1[6]=asc[0];line1[7]=asc[1];BCD_ASCII(time[5],asc); //为第1行的星期赋值line1[9]=asc[1];while(LCD1602_readBF());LCD1602_gotoXY(1,2); //第1行从第3个位置开始显示LCD1602_sendstr("20"); //将07年显示为2007的形式LCD1602_sendstr(line1); //第1行显示while(LCD1602_readBF());LCD1602_gotoXY(2,4); //第2行从第5个位置开始显示LCD1602_sendstr(line2); //第2行显示}void Disp_time2(uchar time[]){uchar i,asc[2];// uchar line1[11]={0,0,'0',0,0,'0',0,0,'0',0,'\0'};//显示第1行的字符数组uchar line1[11]={'*','*','c','l','o','c','k','*','*','*','\0'};//显示第1行的字符数组uchar line2[9]={0,0,':',0,0,':',0,0,'\0'}; //显示第2行的字符数组//uchar line2[9]={0,0,':',0,0,' ',' ',' ','\0'}; //显示第2行的字符数组for(i=0;i<3;i++) //为第2行的字符数组赋值{BCD_ASCII(time[2-i],asc);line2[i*3]=asc[0];line2[i*3+1]=asc[1];}/*BCD_ASCII(time[6],asc); //为第1行的年赋值line1[0]=asc[0];line1[1]=asc[1];BCD_ASCII(time[4],asc); //为第1行的月赋值line1[3]=asc[0];line1[4]=asc[1];BCD_ASCII(time[3],asc); //为第1行的日赋值line1[6]=asc[0];line1[7]=asc[1];BCD_ASCII(time[5],asc); //为第1行的星期赋值line1[9]=asc[1];*/while(LCD1602_readBF());LCD1602_gotoXY(1,2); //第1行从第3个位置开始显示LCD1602_sendstr("**"); //将07年显示为2007的形式LCD1602_sendstr(line1); //第1行显示while(LCD1602_readBF());LCD1602_gotoXY(2,4); //第2行从第5个位置开始显示LCD1602_sendstr(line2); //第2行显示}void Disp_time3(uchar time[]){uchar i,asc[2];uchar line1[11]={0,0,'-',0,0,'-',0,0,' ',0,'\0'};//显示第1行的字符数组uchar line2[9]={0,0,':',0,0,':',0,0,'\0'}; //显示第2行的字符数组for(i=0;i<3;i++) //为第2行的字符数组赋值{BCD_ASCII(time[2-i],asc);line2[i*3]=asc[0];line2[i*3+1]=asc[1];}BCD_ASCII(time[6],asc); //为第1行的年赋值line1[0]=asc[0];line1[1]=asc[1];BCD_ASCII(time[4],asc); //为第1行的月赋值line1[3]=asc[0];line1[4]=asc[1];BCD_ASCII(time[3],asc); //为第1行的日赋值line1[6]=asc[0];line1[7]=asc[1];BCD_ASCII(time[5],asc); //为第1行的星期赋值line1[9]=asc[1];while(LCD1602_readBF());LCD1602_gotoXY(1,2); //第1行从第3个位置开始显示LCD1602_sendstr("20"); //将07年显示为2007的形式LCD1602_sendstr(line1); //第1行显示while(LCD1602_readBF());LCD1602_gotoXY(2,0); //第2行从第5个位置开始显示LCD1602_sendstr("ON ");LCD1602_sendstr(line2); //第2行显示}void Disp_time4(uchar time[]){uchar i,asc[2];uchar line1[11]={0,0,'-',0,0,'-',0,0,' ',0,'\0'};//显示第1行的字符数组uchar line2[9]={0,0,':',0,0,':',0,0,'\0'}; //显示第2行的字符数组for(i=0;i<3;i++) //为第2行的字符数组赋值{BCD_ASCII(time[2-i],asc);line2[i*3]=asc[0];line2[i*3+1]=asc[1];}BCD_ASCII(time[6],asc); //为第1行的年赋值line1[0]=asc[0];line1[1]=asc[1];BCD_ASCII(time[4],asc); //为第1行的月赋值line1[3]=asc[0];line1[4]=asc[1];BCD_ASCII(time[3],asc); //为第1行的日赋值line1[6]=asc[0];line1[7]=asc[1];BCD_ASCII(time[5],asc); //为第1行的星期赋值line1[9]=asc[1];while(LCD1602_readBF());LCD1602_gotoXY(1,2); //第1行从第3个位置开始显示LCD1602_sendstr("20"); //将07年显示为2007的形式LCD1602_sendstr(line1); //第1行显示while(LCD1602_readBF());LCD1602_gotoXY(2,0); //第2行从第5个位置开始显示LCD1602_sendstr("OFF ");LCD1602_sendstr(line2); //第2行显示}void sheng(){for ( w=0;w<1;w++){TCCR1A=0X50;TCCR1B=0X09;OCR1A=5332;Delayms(100);guan();Delayms(100);}}void sheng3(){for ( w=0;w<5;w++){TCCR1A=0X50;TCCR1B=0X09;OCR1A=5332;DS1302_getT(gettime); //获得当前时间Disp_time(gettime); //显示当前时间Delayms(1000);guan();DS1302_getT(gettime); //获得当前时间Disp_time(gettime); //显示当前时间Delayms(1000);}}void sheng2(){for ( w=0;w<1 ;w++){TCCR1A=0X50;TCCR1B=0X09;OCR1A=3999;DS1302_getT(gettime); //获得当前时间Disp_time(gettime); //显示当前时间Delayms(1000);guan();DS1302_getT(gettime); //获得当前时间Disp_time(gettime); //显示当前时间Delayms(1000);}}{TCCR1A=0X00;TCCR1B=0X00;}uchar key_press() //按键响应函数{uchar j;DDRD|=0X0F;PORTD|=0X0F;DDRD&=0XF0;j=PIND;j=j&0X0F;if (j==0X0F){return 0;}else{return 1;}}uchar key_scan() //按键扫描函数{uchar key;Delayms(100);if (key_press()){key=PIND;key&=0X0F;switch(key){case 0X0E:if (num<2){num++;key=5;else{key=2;num=1;}break;case 0X0D://判断闹钟开关if (num<2){num1=num;num++;key=4;key1=4;// key2=0x0D;}else{num=1;num1=num;key=7;key1=7;// key2=0x0D;}break;case 0X0B: //判断进入实时时间或闹钟时间if (flag){key=3;//调闹钟时间}elsekey=6;//调实时时间break;case 0X07:if(flag){if (num<3){num1=num;num++;o=1;key=1;}else{num=1;num1=num;o=1;key=1;}}else{if (num<8){num1=num;num++;o=1;key=0;}else{num=1;num1=num;o=1;key=0;}}break;default:key=16;}while (key_press()); }else{key=16;}return key;}void setime(){if (num1==6){if(o<99)o++;else{o=1;}}if (num1==5){if(o<7)o++;else{o=1;}}if (num1==4){if(o<12)o++;else{o=1;}}if (num1==3){if(o<31)o++;else{o=1;}}if (num1==2){if(o<23)o++;else{o=0;}}if (num1==1){if(o<59)o++;else{o=0;}}}/*******************************************函数名称: main功能: 1. 在1602液晶上显示当前时间2.可以设置时间(M1-M9为数字0-9,M13为设置模式和显示模式选择,M14为当前设置位选择)参数: 无返回值: 无/********************************************/void main(void){ uchar k,z;int i,j;int shu;int shu1;uint mu,sic;uchar setadd,setdat,shift; //setadd指定将当前数值送入DS1302的哪个寄存器//setdat是当前设置的数值,即被送入DS1302指定寄存器的数//shift来实现十位和各位的设置相互独立(因为十位和个位是在一个寄存器里的)uchar dis_x,dis_y; //存储1602液晶当前光标的位置uchar time[7];uchar time2[7];uchar time3[7];uchar time4[7];uchar settime[7];uchar a=0x30 ;uchar b=0x01 ;uchar c=0x01;uchar d=0x01 ;uchar e=0x01 ;uchar f=0x01 ;uchar g=0x01 ;time[0]=a;time[1]=b;time[2]=c;time[3]=d;time[4]=e;time[5]=f;time[6]=g;for (i=0;i<7;i++ ) {settime[i]=time[i]; }time2[0]=0x00; time2[1]=0x00; time2[2]=0x00; time2[3]=0x00; time2[4]=0x00; time2[5]=0x00; time2[6]=0x00;for (j=0;j<7;j++ ) {gettime[j]=time2[j]; }DDRD|=0X30;//uchar settime[7]={0x50,0x59,0x23,0x01,0x01,0x06,0x07};//设置的秒,分,时,日,月,星期,年//uchar gettime[7]={0x00,0x00,0x00,0x00,0x00,0x00,0x00};//保存当前时间的数组LCD1602_initial(); //初始化1602液晶DS1302_portinit(); //初始化DS1302的三根数据线DS1302_init(); //启动振荡器,DS1302开始工作//DS1302_setT(settime); //设置初始时间while(1) //以下程序完成显示和设置时间{k=key_press();if (k){z=key_scan();switch (z){case 0://选择分时年月星期sheng();if (num1>2){shu1=1;}elseshu1=2;time[num1]=time11[o];shu=num1-1;settime[num1]=time[num1];Delayms(5);break;case 1://切换闹钟的分时sheng();if (num1>2){shu1=1;}elseshu1=2;time[num1]=time11[o];shu=num1-1;settime[num1]=time[num1];Delayms(5);break;case 2:sheng();flag=0;o=0;break;case 3://调闹钟时间sheng();clock[num1]=time11[o];setime( );break;case 4://关闹钟sheng();flag1=1;break;case 5://切换闹钟sheng();flag=1;o=0;break;case 6://调实时时间sheng();Delayms(10);time[num1]=time11[o];setime( );settime[num1]=time[num1];DS1302_setT(settime); //设置初始时间break;case 7: //开闹钟sheng();flag1=0;break;}}DS1302_getT(gettime); //获得当前时间time4[2]=DS1302_readD(0x84|RD);//时time4[1]=DS1302_readD(0x82|RD); //分time4[0]=DS1302_readD(0x80|RD);//秒Delayms(80);if (flag){Disp_time2(clock);//显示闹钟时间}else{if (key1==7)Disp_time3(gettime); //显示当前时间elseDisp_time4(gettime);}if (num1==7){LCD1602_sendbyte(iCmd,LCDa_CUROFF);// LCD1602_sendbyte(iCmd,LCDa_OFF);}else{LCD1602_gotoXY(shu1,guangbiao[shu]);LCD1602_sendbyte(iCmd,LCDa_CURON);LCD1602_sendbyte(iCmd,LCDa_CURFLA);}if ((time4[1]==0x59)&(time4[0]==0x49))//整点报时{sheng3();sheng2();}if ((clock[1]==time4[1])&(clock[2]==time4[2]))//音乐闹钟{yinyuenaozhong(mu,sic);}}}。