一、采用内部定时的程序:(注意,程序中应用的是共阴极数码管)#include<reg52.h>#define uint unsigned int#define uchar unsigned charuchar code Dis_code[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//共阴极数码管编码sbit P10=P1^0;sbit P11=P1^1;sbit P12=P1^2;sbit P13=P1^3;uchar cnt,seccnt,mincnt,hourcnt,daycnt,moncnt,yearcnt;ucharseccnt1,seccnt10,mincnt1,mincnt2,hourcnt1,hourcnt10,daycnt1,daycnt10,moncnt1,moncn t10,year1,year10;void delay(unsigned char i) //延时子程序{unsigned char j;while((i--)!=0){for(j=625;j>0;j--);}}void Display(time0,time1,time2,time3){P2=0x07;P0=Dis_code[time0];delay(1);P2=0x0b;P0=Dis_code[time1];delay(1);P2=0x0d;P0=Dis_code[time2]|0x80;delay(1);P2=0x0e;P0=Dis_code[time3];delay(1);}void main(){seccnt1,seccnt10,mincnt1,mincnt10,hourcnt1,hourcnt10,daycnt1,daycnt10,moncnt1,monc nt10,yearcnt1,yearcnt10;uchar m=0,flag;yearcnt=11;moncnt=10;daycnt=12;TMOD=0X01;TH1=0X3C;TL1=0XAE;//定时器设置初值15535,定时50msTR1=1;EA=1;ET1=1;P10=0;while(1){if(cnt==20){cnt=0;seccnt++;if(seccnt==60){ seccnt=0;mincnt++;if(mincnt==60){mincnt=0;hourcnt++;if(hourcnt==24){hourcnt=0;daycnt++;if(daycnt==31){daycnt=1;moncnt++;if(moncnt==13){moncnt=1;yearcnt++;if(yearcnt==100)yearcnt=0;}}}}}}}if(P11==0)//翻页按钮{ //flag=0;delay(100);if(P11==0){m++;//页码控制if(m>2){m=0;}}}while(P11==0);if(P12==0)//调节时间的按钮{delay(100);if(P12==0){ TR1=~TR1;//按下一次停止计时,再按一次开始计时 }}while(P12==0);if(TR1==0)//如果计时停止,开始校正时间{if(P13==0){delay(100);if(P13==0){flag++;}}while(P13==0);}else flag=0;switch(m){case 0:if(flag>0){flag--;mincnt++;mincnt=mincnt%60;}seccnt1=seccnt%10;seccnt10=seccnt/10;mincnt1=mincnt%10;mincnt10=mincnt/10;Display(seccnt1,seccnt10,mincnt1,mincnt10);break;case 1:if(flag>0){flag--; hourcnt++; daycnt=(daycnt|(hourcnt/24))%30; hourcnt=hourcnt %24;}// hourcnt=(hourcnt|flag)%24;hourcnt1=hourcnt%10;hourcnt10=hourcnt/10;daycnt1=daycnt%10;daycnt10=daycnt/10;Display(hourcnt1,hourcnt10,daycnt1,daycnt10);break;case 2:if(flag>0){flag--; moncnt++; moncnt=moncnt%13;if(moncnt==0){moncnt++;yearcn t++;}}moncnt1=moncnt%10;moncnt10=moncnt/10;yearcnt1=yearcnt%10;yearcnt10=yearcnt/10;Display(moncnt1,moncnt10,yearcnt1,yearcnt10);break;}}}void Time1() interrupt 3{TH1=0X3C;TL1=0XAE;cnt++;}二、采用DS1302的程序(应用上面的电路图,数码管为共阳极型)#include <reg52.h>//定义共阳极字型码0123456789-unsigned char codedispcode[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};unsigned char time[]={0,0,0,0};//用来储存分秒unsigned char date[]={0,0,0,0};//用来储存日时unsigned char year[]={0,0,0,0};//用来储存年月typedef struct __SYSTEMTIME__{unsigned char Second;unsigned char Minute;unsigned char Hour;unsigned char Week;unsigned char Day;unsigned char Month;unsigned char Year;unsigned char DateString[9];unsigned char TimeString[9];}SYSTEMTIME; //定义的时间类型SYSTEMTIME time1;sbit DS1302_CLK = P1^6; //实时时钟时钟线引脚sbit DS1302_IO = P1^7; //实时时钟数据线引脚sbit DS1302_RST = P1^5; //实时时钟复位线引脚sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;sbit P10=P1^0;sbit P11=P1^1;sbit P12=P1^2;sbit P13=P1^3;sbit P14=P1^4;//#define AM(X) X//#define PM(X) (X+12) // 转成24小时制#define DS1302_SECOND 0x80 //秒寄存器#define DS1302_MINUTE 0x82 //分寄存器#define DS1302_HOUR 0x84#define DS1302_WEEK 0x8A#define DS1302_DAY 0x86#define DS1302_MONTH 0x88#define DS1302_YEAR 0x8C#define DS1302_RAM(X) (0xC0+(X)*2) //用于计算DS1302_RAM 地址的宏void DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数) {unsigned char i;ACC = d;for(i=8; i>0; i--){DS1302_IO = ACC0; //相当于汇编中的RRCDS1302_CLK = 1;DS1302_CLK = 0; //发一个高跳变到低的脉冲ACC = ACC >> 1;}}unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数) {unsigned char i;for(i=8; i>0; i--){ACC = ACC >>1; //相当于汇编中的RRCACC7 = DS1302_IO;DS1302_CLK = 1;DS1302_CLK = 0; //发一个高跳变到低的脉冲}return(ACC);}void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据{DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr); // 地址,命令DS1302InputByte(ucDa); // 写1Byte数据DS1302_CLK = 1;DS1302_RST = 0; //RST 0->1->0,CLK 0->1}unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据{unsigned char ucData;DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1; //enableDS1302InputByte(ucAddr|0x01); // 地址,命令ucData = DS1302OutputByte(); // 读1Byte数据DS1302_CLK = 1; //RST 0->1->0,CLK 0->1DS1302_RST = 0;return(ucData);}void DS1302_SetProtect(bit flag) //是否写保护{if(flag)Write1302(0x8E,0x10); //WP=1,不能写入elseWrite1302(0x8E,0x00);//WP=0,可以写入}void DS1302_SetTime(unsigned char Address, unsigned char Value) // 设置时间函数{DS1302_SetProtect(0);Write1302(Address, ((Value/10)<<4 | (Value%10))); //高4位为十位,低4位为个位}void DS1302_GetTime(SYSTEMTIME *Time){unsigned char ReadValue;ReadValue = Read1302(DS1302_SECOND);Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//转换成10进制的秒ReadValue = Read1302(DS1302_MINUTE);Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_HOUR);Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_DAY);Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_WEEK);Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_MONTH);Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_YEAR);Time->Year = ((ReadValue&0xf0)>>4)*10 + (ReadValue&0x0F);}void Initial_DS1302(void){unsigned char Second=Read1302(DS1302_SECOND);if(Second&0x80) //如果第七为1(表明没有启动), 则启动时钟DS1302_SetTime(DS1302_SECOND,0);}void delay(unsigned char i) //延时子程序{unsigned char j;while((i--)!=0){for(j=625;j>0;j--);}}/*unsigned char button_time(n,x,y) //时钟调整子程序unsigned char n,x,y;{if(P1^7==0){delay(50);if(P1^7==0){n++;if(n==x)n=0;while(P1^7==0);}}if(P1^1==0){delay(50);if(P1^1==0){if(n==0)n=y;elsen--;while(P1^1==0);}}return n;}*//*unsigned char button_date(n,x,y) //日期调整子程序unsigned char n,x,y;{if(P1^7==0){delay(50);if(P1^7==0){n++;if(n==x)n=1;while(P1^7==0);}}if(P1^1==0){delay(50);if(P1^1==0){if(n==1)n=y;elsen--;while(P1^1==0);}}return n;}*/void display1(minute10,minute1,second10,second1) //显示第一页分秒子程序//unsigned char second10,second1,minute10,minute1;{P2=0x08;P0=dispcode[second1];//显示秒的个位delay(1);P2=0x04;P0=dispcode[second10]; //显示秒的十位delay(1);P2=0x02;P0=dispcode[minute1]; //显示分的个位delay(1);P2=0x01;P0=dispcode[minute10];//显示分的十位delay(1);}void display2(data10,data1,hour10,hour1) //显示第二页天时子程序//unsigned char data10,data1,hour10,hour1;{P2=0xf8;P0=dispcode[data1];//显示天的个位delay(1);P2=0xf4;P0=dispcode[data10]; //显示天的十位delay(1);P2=0xf2;P0=dispcode[hour1]; //显示时的个位delay(1);P2=0xf1;P0=dispcode[hour10];//显示时的十位delay(1);}void display3(year10,year1,month10,month1) //显示第三页年月子程序//unsigned char year10,year1,month10,month1;{P2=0xf2;P0=dispcode[month1];//显示月的个位delay(1);P2=0xf1;P0=dispcode[month10]; //显示月的十位delay(1);P2=0xf8;P0=dispcode[year1]; //显示月的个位delay(1);P2=0xf4;P0=dispcode[year10];//显示月的十位delay(1);}void main(){unsigned char flag=0;Initial_DS1302(); //初始化DS1302这个时钟芯片,P10=0; //点亮测试灯while(1){DS1302_GetTime(&time1); //读取时间参数time[3]=(time1.Second)%10; //把秒的个位数据存入time[3]time[2]=(time1.Second)/10; //把秒的十位数据存入time[2]time[1]=(time1.Minute)%10; //把分的个位数据存入time[1]time[0]=(time1.Minute)/10; //把分的十位数据存入time[0]date[3]=(time1.Day)%10;date[2]=(time1.Day)/10;date[1]=(time1.Hour)%10;date[0]=(time1.Hour)/10;year[3]=(time1.Year)%10;year[2]=(time1.Year)/10;year[1]=(time1.Month)%10;year[0]=(time1.Month)/10;// display1(time[0],time[1],time[2],time[3]);if(P11==0){delay(50);if(P11==0){flag++;if(flag>2)//flag: 1 显示第二页日时;2 显示第三页年月0:显示第一页分秒{flag=0;}}while(P11==0);}/*if(P1^6==0) //如果按下Time Set键一下,开始显示日期,再按一下进入日期跟时钟的调节模式{delay(50);if(P1^6==0){flag++;if(flag>6){flag=0;}}while(P1^6==0);}*/switch(flag){case 0:display1(time[0],time[1],time[2],time[3]); //调用子函数display,把存入数组time 的数据给显示出来break;case 1:display2(date[0],date[1],date[2],date[3]); //调用子函数display,把存入数组date 的数据给显示出来break;case 2:display3(year[0],year[1],year[2],year[3]);break;/* case 3:time1.Month=button_date(time1.Month,13,12); //调整月DS1302_SetTime(0x88,time1.Month);display(10,10,date[2],date[3]);break;case 4:time1.Day=button_date(time1.Day,32,31); //调整日DS1302_SetTime(0x86,time1.Day);display(10,10,date[4],date[5]);break;case 5:time1.Minute=button_time(time1.Minute,60,59); //调整分DS1302_SetTime(0x82,time1.Minute);display(time[2],time[3],10,10);break;case 6:time1.Second=button_time(time1.Second,60,59); //调整秒DS1302_SetTime(0x80,time1.Second);display(10,10,time[4],time[5]);break;*/}}}。