《2022年51单片机电子日历课程设计.doc》由会员分享,可在线阅读,更多相关《2022年51单片机电子日历课程设计.doc(13页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、51单片机电子日历课程设计程序代码:/*/* 电子日历,有时间显示、闹铃、日期、秒表及键盘设置功能 */* 功能键A: 设置位数字+1 闹钟形式下为闹钟开关 秒表形式下为记时开关 */* 功能键B: 设置位数字-1 闹钟形式下为闹钟开关 */* 功能键C:设置形式及设置位选择 秒表形式下为清零键 */ /* 功能键D:在四种工作形式下切换 设置闹钟开关 */ /* 曹宇 03电子 0201029 */* 2006.6.3 更新 */*/#include #include /*这里设置程序初始化时显示的时间*/#define SET_HOUR 12 /*设置初始化小时*/#define SET_
2、MINUTE 00 /*设置初始化分钟*/#define SET_SECOND 00 /*设置初始化秒数*/*系统地址*/#define BASE_PORT 0x8000 /*选通基地址*/#define KEY_LINE BASE_PORT+1 /*键盘行线地址*/#define KEY_COLUMN BASE_PORT+2 /*键盘列线地址*/#define LED_SEG BASE_PORT+4 /*数码管段选地址*/#define LED_BIT BASE_PORT+2 /*数码管位选地址*/#define LED_ON(x) XBYTELED_BIT=(0x01#define LED
3、_OFF XBYTELED_SEG=0x00 /*LED显示空*/*在设置形式下对秒分时的宏定义*/#define SECOND 0 /*对应数码管右边两位*/#define MINUTE 1 /*对应数码管中间两位*/#define HOUR 2 /*对应数码管左边两位*/*定义四种工作形式*/#define CLOCK clockstr /*时钟形式*/#define ALART alartstr /*闹钟形式*/#define DATE datestr /*日期形式*/#define TIMER timerstr /*秒表形式*/*以下是所有子函数的声明*/void sys_init(v
4、oid); /*系统的初始化程序*/void display(void); /*动态刷新一次数码管子程序*/void clockplus(void); /*时间加1S的子程序*/void update_clockstr(void); /*更新时间显示编码*/void update_alartstr(void); /*更新闹钟时间的显示编码*/void update_datestr(void); /*更新日期显示编码*/void update_timerstr(void); /*更新秒表时间的显示编码*/void deley(int); /*延时子程序*/void update_dispbuf(
5、unsigned char *); /*更新显示缓冲区*/unsigned char getkeycode(void); /*获取键值子程序*/void keyprocess(unsigned char); /*键值处理子程序*/unsigned char getmonthdays(unsigned int,unsigned char);/*计算某月的天数子程序*/*功能键功能子函数*/void Akey(void); /*当前设置位+1 开关闹钟 开关秒表*/void Bkey(void); /*当前设置位-1 开关闹钟 */void Ckey(void); /*设置位选择 秒表清零*/vo
6、id Dkey(void); /*切换四种工作形式*/*全局变量声明部分*/unsigned char led10=0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F;/*从09的LED编码*/unsigned char ledchar3=0x5c,0x54,0x71;/*o n f*/unsigned char key24= /* 键值代码数组 对应键位:*/ 0x70,0x71,0x72,0x73,0x74,0x75, /* 7 8 9 A TRACE RESET*/ 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5, /* 4 5
7、 6 B STEP MON */ 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5, /* 1 2 3 C HERE LAST */ 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5; /* 0 F E D EXEC NEXT */struct /*时间构造体变量*/ unsigned char s; unsigned char m; unsigned char h; clock=SET_SECOND,SET_MINUTE,SET_HOUR;struct /*闹铃时间构造体变量*/ unsigned char m; unsigned char h; alart=SET_MI
8、NUTE,SET_HOUR;struct /*日期构造体变量*/ unsigned int year; unsigned char month; unsigned char day; date=6,1,1;struct /*秒表时间构造体变量*/ unsigned char ms; unsigned char s; unsigned char m; timer=0,0,0;unsigned char dispbuf6; /*显示缓冲区数组*/unsigned char clockstr6; /*时间显示的数码管编码数组*/unsigned char alartstr6; /*闹钟显示的数码管编
9、码数组*/unsigned char datestr6; /*日期显示的数码管编码数组*/unsigned char timerstr6; /*秒表显示的数码管编码数组*/unsigned int itime=0,idot; /*定时器0中断计数*/unsigned char itime1=0; /*定时器1中断计数*/sbit P3_1=P31; /*外接蜂鸣器的管脚*/bdata bit IsSet=0; /*设置形式标志位 0:正常走时 1:设置形式*/bdata bit Alart_EN=0; /*闹铃功能同意位 0:禁止闹铃 1:同意闹铃*/bdata bit IsBeep=0; /
10、*响铃标志位 0:未响铃 1:正在响铃*/unsigned char SetSelect=0; /*在设置形式IsSet=1时,正在被设置的位,对应上面的宏*/unsigned char *CurrentMode; /*标志当前正设置的功能,如CurrentMode=CLOCK或CurrentMode=ALART等*/void timerplus(void);/*函数部分*/void main(void) sys_init(); while(1) XBYTEKEY_COLUMN,0x00; /*给键盘列线赋全零码,推断是否有键按下 */ while(XBYTEKEY_LINE0x0f)=0x0
11、f) /*检测是否有键按下,无则不断进展LED的刷新显示*/ if(Alart_EN(clock.h=alart.h)(clock.m=alart.m) IsBeep=1; else IsBeep=0; P3_1=0; display(); keyprocess(getkeycode(); /*有键按下时得到键值,并送入键值处理程序*/ display(); /*可要可不要*/ void sys_init(void) TMOD=0x22; /*定时器0和1都设置为工作方式2,基准定时2502500us=0.5ms*/ TH0=6; /*定时器0中断效劳用来产生1秒时钟定时及闹钟蜂鸣器蜂鸣脉冲*
12、/ 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;
13、/*蜂鸣器接线引脚复位*/void timer0(void) interrupt 1 using 1 /*定时器0中断效劳器,用来产生1秒定时*/ itime+; if(itime=1000) if(IsSet) /*在设置形式下,对正在设置的位闪耀显示*/ dispbufSetSelect*2=0; /*对正在设置的位所对应的显示缓冲区元素赋0,使LED灭*/ dispbufSetSelect*2+1=0; if(IsBeep) P3_1=!P3_1; /*闹钟形式时,产生峰鸣器响脉冲*/ if(CurrentMode=CLOCK) dispbuf2=dispbuf20x7f; dispbu
14、f4=dispbuf40x7f; if(itime=2000) /*两千次计数为1S 20000.5ms=1s*/ itime=0; /*定时1s时间到,软计数清零*/ clockplus(); /*时间构造体变量秒数加1 */ update_clockstr(); /* 更新时间显示编码数组 */ if(CurrentMode!=TIMER) update_dispbuf(CurrentMode); /* 用时间编码数组更新显示缓冲区 */ void timer1(void) interrupt 3 using 2 /*定时器1中断效劳器,用来产生1/100秒定时*/ idot+; if(+
15、itime1=20) /*20*0.5ms=10ms*/ itime1=0; timerplus(); update_timerstr(); if(CurrentMode=TIMER) update_dispbuf(timerstr); dispbuf2=dispbuf20x7f; /*关闭小数点的显示*/ dispbuf4=dispbuf40x7f; if(idot1000) /*闪耀显示小数点*/ dispbuf2=dispbuf2|0x80; dispbuf4=dispbuf4|0x80; else dispbuf2=dispbuf20x7f; dispbuf4=dispbuf40x7f
16、; if(idot=2000) idot=0;/*功能模块子函数*/void clockplus(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) date.month=1; void timerplus() /*秒表1
17、/100秒位加1,推断秒、分子程序*/ if(+timer.ms=100) timer.ms=0; if(+timer.s=60) timer.s=0; if(+timer.m=60) timer.m=0; void update_clockstr(void) /*更新时钟显示代码数组clockstr*/ clockstr0=ledclock.s%10; /*给元素0赋相应数码管显示编码,编码序号是秒数的个位*/ clockstr1=led(int)(clock.s/10); /*给元素1赋相应数码管显示编码,编码序号是秒数的十位*/ clockstr2=ledclock.m%10; /*以下
18、类推*/ clockstr3=led(int)(clock.m/10); clockstr4=ledclock.h%10; clockstr5=led(int)(clock.h/10);void update_alartstr(void) /*更新闹钟显示代码数组alartstr*/ /*右边两位显示on:闹钟开启 of:闹钟关闭*/ if(Alart_EN) alartstr0=ledchar1;/*显示字母n*/ else alartstr0=ledchar2; /*显示字母f*/ alartstr1=ledchar0; /*显示字母o*/ alartstr2=ledalart.m%10;
19、 alartstr3=led(int)(alart.m/10); alartstr4=ledalart.h%10; alartstr5=led(int)(alart.h/10);void update_datestr(void) /*更新日期显示代码数组datestr*/ datestr0=leddate.day%10; datestr1=led(int)(date.day/10); datestr2=leddate.month%10; datestr3=led(int)(date.month/10); datestr4=leddate.year%10; datestr5=led(int)(d
20、ate.year/10);void update_timerstr(void) /*更新秒表显示代码数组timerstr*/ timerstr0=ledtimer.ms%10; timerstr1=led(int)(timer.ms/10); timerstr2=ledtimer.s%10; timerstr3=led(int)(timer.s/10); timerstr4=ledtimer.m%10; timerstr5=led(int)(timer.m/10);void display(void) /*刷新显示六位LED一次*/ unsigned char i; for(i=0;i1; /
21、*列码右移一位*/ icolumn+; /*列号加1*/ keycode=keycode4; /*把行码移到高四位*/ keycode=keycode|icolumn; /*由行码和列码组成键码*/ /等待按键放开 XBYTEKEY_COLUMN=0x00; while(XBYTEKEY_LINE0x0f)!=0x0f) display(); return keycode;void keyprocess(unsigned char keycode) /*键值处理函数*/ switch (keycode) case 0x73: Akey(); break; case 0xB3: Bkey();
22、break; case 0xD3: Ckey(); break; case 0xE3: Dkey(); break; default: break; update_dispbuf(CurrentMode);unsigned char getmonthdays(unsigned int year,unsigned char month)/*得到某月的天数*/ unsigned char days; switch (month) case 4: case 6: case 9: case 11:days=30; break; case 2: if(year%4=0) days=29; else da
23、ys=28; break; default:days=31; break; return days;/*功能键子函数部分*/void Akey(void) /*对当前设置位进展加一操作,假如设置秒位,则给秒位清零*/ if(CurrentMode=TIMER) /*秒表形式下启闭走时*/ TR1=!TR1; return; if(!IsSet) return; /*假如不是设置形式退出*/ switch (SetSelect) case SECOND:if(CurrentMode=CLOCK) clock.s=0; /*假如当前被设置位是秒位,则清零秒位*/ update_clockstr()
24、; if(CurrentMode=ALART) Alart_EN=!Alart_EN; update_alartstr(); if(CurrentMode=DATE) if(+date.day=(getmonthdays(date.year,date.month)+1) date.day=1; update_datestr(); if(CurrentMode=TIMER) TR1=!TR1; break; case MINUTE:if(CurrentMode=CLOCK) if(+clock.m=60) clock.m=0; /*假如当前被设置分位,则分位加1*/ update_clockst
25、r(); if(CurrentMode=ALART) if(+alart.m=60) alart.m=0; update_alartstr(); if(CurrentMode=DATE) if(+date.month=13) date.month=1; update_datestr(); break; case HOUR: if(CurrentMode=CLOCK) if(+clock.h=24) clock.h=0; /*假如当前被设置时位,则时位加1*/ update_clockstr(); if(CurrentMode=ALART) if(+alart.h=24) alart.h=0;
26、update_alartstr(); if(CurrentMode=DATE) if(+date.year=100) date.year=0; update_datestr(); break; default: break; update_dispbuf(CurrentMode);void Bkey(void) /*对当前设置位进展减一操作,假如设置秒分,则给秒位清零,类比Akey()函数*/ if(!IsSet) return; switch (SetSelect) case SECOND:if(CurrentMode=CLOCK) clock.s=0; update_clockstr();
27、 if(CurrentMode=ALART) Alart_EN=!Alart_EN; update_alartstr(); if(CurrentMode=DATE) if(-date.day=0x00) date.day=getmonthdays(date.year,date.month); update_datestr(); break; case MINUTE:if(CurrentMode=CLOCK) if(-clock.m=0xff) clock.m=59; update_clockstr(); if(CurrentMode=ALART) if(-alart.m=0xff) alart.m=59; update_alartstr(); if(CurrentMode=DATE) if(-date.month=0x00) date.month=12; update_datestr(); break; case HOUR: if(CurrentMode=CLOCK) if(-clock.h=0xff) clock.h=23; update_clockstr();
限制150内