51单片机电子日历课程设计程序代码:/****************************************************************************//*电子日历,有时间显示、闹铃、日期、秒表及键盘设置功能*//*功能键A:设置位数字+1闹钟模式下为闹钟开关秒表模式下为记时开关*//*功能键B:设置位数字-1闹钟模式下为闹钟开关*//*功能键C:设置模式及设置位选择秒表模式下为清零键*//*功能键D:在四种工作模式下切换设置闹钟开关*//*曹宇03电子0201029*//*2006.6.3更新*//****************************************************************************/#include#include/***************这里设置程序初始化时显示的时间****************/#defineSET_HOUR12/*设置初始化小时*/#defineSET_MINUTE00/*设置初始化分钟*/#defineSET_SECOND00/*设置初始化秒数*//*************************系统地址****************************/#defineBASE_PORT0x8000/*选通基地址*/#defineKEY_LINEBASE_PORT+1/*键盘行线地址*/#defineKEY_COLUMNBASE_PORT+2/*键盘列线地址*/#defineLED_SEGBASE_PORT+4/*数码管段选地址*/#defineLED_BITBASE_PORT+2/*数码管位选地址*/#defineLED_ON(x)XBYTE[LED_BIT]=(0x01#defineLED_OFFXBYTE[LED_SEG]=0x00/*LED显示空*//**************在设置模式下对秒分时的宏定义*****************/#defineSECOND0/*对应数码管右边两位*/#defineMINUTE1/*对应数码管中间两位*/#defineHOUR2/*对应数码管左边两位*//********************定义四种工作模式***********************/#defineCLOCKclockstr/*时钟模式*/#defineALARTalartstr/*闹钟模式*/#defineDATEdatestr/*日期模式*/#defineTIMERtimerstr/*秒表模式*//****************以下是所有子函数的声明*********************/voidsys_init(void);/*系统的初始化程序*/voiddisplay(void);/*动态刷新一次数码管子程序*/voidclockplus(void);/*时间加1S的子程序*/voidupdate_clockstr(void);/*更新时间显示编码*/voidupdate_alartstr(void);/*更新闹钟时间的显示编码*/voidupdate_datestr(void);/*更新日期显示编码*/voidupdate_timerstr(void);/*更新秒表时间的显示编码*/voiddeley(int);/*延时子程序*/voidupdate_dispbuf(unsignedchar*);/*更新显示缓冲区*/unsignedchargetkeycode(void);/*获取键值子程序*/voidkeyprocess(unsignedchar);/*键值处理子程序*/unsignedchargetmonthdays(unsignedint,unsignedchar);/*计算某月的天数子程序*//*功能键功能子函数*/voidAkey(void);/*当前设置位+1开关闹钟开关秒表*/voidBkey(void);/*当前设置位-1开关闹钟*/voidCkey(void);/*设置位选择秒表清零*/voidDkey(void);/*切换四种工作模式*//**********************全局变量声明部分*********************/unsignedcharled[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};/*从0~9的LED编码*/unsignedcharledchar[3]={0x5c,0x54,0x71};/*onf*///unsignedcharkey[24]={/*键值代码数组对应键位:*///0x70,0x71,0x72,0x73,0x74,0x75,/*789ATRACERESET*///0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,/*456BSTEPMON*///0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,/*123CHERELAST*///0xe0,0xe1,0xe2,0xe3,0xe4,0xe5};/*0FEDEXECNEXT*/struct{/*时间结构体变量*/unsignedchars;unsignedcharm;unsignedcharh;}clock={SET_SECOND,SET_MINUTE,SET_HOUR};struct{/*闹铃时间结构体变量*/unsignedcharm;unsignedcharh;}alart={SET_MINUTE,SET_HOUR};struct{/*日期结构体变量*/unsignedintyear;unsignedcharmonth;unsignedcharday;}date={6,1,1};struct{/*秒表时间结构体变量*/unsignedcharms;unsignedchars;unsignedcharm;}timer={0,0,0};unsignedchardispbuf[6];/*显示缓冲区数组*/unsignedcharclockstr[6];/*时间显示的数码管编码数组*/unsignedcharalartstr[6];/*闹钟显示的数码管编码数组*/unsignedchardatestr[6];/*日期显示的数码管编码数组*/unsignedchartimerstr[6];/*秒表显示的数码管编码数组*/unsignedintitime=0,idot;/*定时器0中断计数*/unsignedcharitime1=0;/*定时器1中断计数*/sbitP3_1=P3^1;/*外接蜂鸣器的管脚*/bdatabitIsSet=0;/*设置模式标志位0:正常走时1:设置模式*/bdatabitAlart_EN=0;/*闹铃功能允许位0:禁止闹铃1:允许闹铃*/bdatabitIsBeep=0;/*响铃标志位0:未响铃1:正在响铃*/unsignedcharSetSelect=0;/*在设置模式IsSet=1时,正在被设置的位,对应上面的宏*/unsignedchar*CurrentMode;/*标志当前正设置的功能,如CurrentMode=CLOCK或CurrentMode=ALART等*/voidtimerplus(void);/**************************函数部分*************************/voidmain(void){sys_init();while(1){XBYTE[KEY_COLUMN,0x00];/*给键盘列线赋全零扫描码,判断是否有键按下*/while((XBYTE[KEY_LINE]&0x0f)==0x0f)/*检测是否有键按下,无则一直进行LED的刷新显示*/{if(Alart_EN&&(clock.h==alart.h)&&(clock.m==alart.m)){IsBeep=1;}else{IsBeep=0;P3_1=0;}display();}keyprocess(getkeycode());/*有键按下时得到键值,并送入键值处理程序*/display();/*可要可不要*/}}voidsys_init(void){TMOD=0x22;/*定时器0和1都设置为工作方式2,基准定时250×2=500us=0.5ms*/TH0=6;/*定时器0中断服务用来产生1秒时钟定时及闹钟蜂鸣器蜂鸣脉冲*/TL0=6;/*定时器1中断服务留给秒表使用,产生1/100秒定时*/TH1=6;TL1=6;ET0=1;ET1=1;EA=1;TR0=1;update_clockstr();/*初始化时钟显示编码数组*/update_alartstr();/*初始化闹钟显示编码数组*/update_datestr();/*初始化日期显示编码数组*/update_timerstr();/*初始化秒表显示编码数组*/update_dispbuf(clockstr);/*初始化显示缓冲数组*/CurrentMode=CLOCK;/*默认的显示摸式为时钟*/P3_1=0;/*蜂鸣器接线引脚复位*/}voidtimer0(void)interrupt1using1/*定时器0中断服务器,用来产生1秒定时*/{itime++;if(itime==1000){if(IsSet)/*在设置模式下,对正在设置的位闪烁显示*/{dispbuf[SetSelect*2]=0;/*对正在设置的位所对应的显示缓冲区元素赋0,使LED灭*/dispbuf[SetSelect*2+1]=0;}if(IsBeep)P3_1=!P3_1;/*闹钟模式时,产生峰鸣器响脉冲*/if(CurrentMode==CLOCK){dispbuf[2]=dispbuf[2]&0x7f;dispbuf[4]=dispbuf[4]&0x7f;}}if(itime==2000)/*两千次计数为1S2000×0.5ms=1s*/{itime=0;/*定时1s时间到,软计数清零*/clockplus();/*时间结构体变量秒数加1*/update_clockstr();/*更新时间显示编码数组*/if(CurrentMode!=TIMER)update_dispbuf(CurrentMode);/*用时间编码数组更新显示缓冲区*/}}voidtimer1(void)interrupt3using2/*定时器1中断服务器,用来产生1/100秒定时*/{idot++;if(++itime1==20)/*20*0.5ms=10ms*/{itime1=0;timerplus();update_timerstr();if(CurrentMode==TIMER){update_dispbuf(timerstr);dispbuf[2]=dispbuf[2]&0x7f;/*关闭小数点的显示*/dispbuf[4]=dispbuf[4]&0x7f;if(idot1000)/*闪烁显示小数点*/{dispbuf[2]=dispbuf[2]|0x80;dispbuf[4]=dispbuf[4]|0x80;}else{dispbuf[2]=dispbuf[2]&0x7f;dispbuf[4]=dispbuf[4]&0x7f;}}}if(idot==2000)idot=0;}/*功能模块子函数*/voidclockplus(void)/*时间加1s判断分,时子函数*/{if(++clock.s==60)/*秒位判断*/{clock.s=0;if(++clock.m==60)/*分位判断*/{clock.m=0;if(++clock.h==24)/*时位判断*/{clock.h=0;if(++date.day==(getmonthdays(date.year,date.month)+1)){date.day=1;if(++date.month==13)