基于c51功能最全的电子钟程序(lcd1602).doc
功能最全的电子钟【单片机】c51数字时钟(带年月日显示)摘要:本设计以单片机为核心,lcd1602显示。采用独立键盘输入能任意修改当前时间日期和设定闹钟时间。具有显示年月日(区分闰年和二月),闹钟报警和整点报时功能主程序:/* lcd1602电子钟 */# include <reg52.h># include "lcd16024.h"sbit key1 = P20;/调整sbit key2 = P21;/加1sbit key3 = P22;/减1sbit speaker = P23;/蜂鸣器sbit key4 = P24;/闹钟设计bit cal_year = 1;/进入判断闰年标志位bit leap_year;/闰年标志位bit calculate = 0;/日加一标记bit run = 0;/闹钟标志bit beep = 0;/整点报时标志/uint8 num = 0;/调整是给的脉冲uint8 code str1 = "D: "uint8 code str2 = "T: "uint8 code str3 = "Wek"uint8 daystr="2013-07-29 "/年月日格式uint8 timestr="21:30:59 N" /时分秒格式uint8 daystr1="2013-07-29 "/闹钟年月日格式uint8 timestr1="21:30:59 N" /闹钟时分秒格式uint8 numweek = 0;/星期加1标记char week = 1;/星期char sec = 53;/秒char min = 50;/分char hour = 23;/时uint8 day = 30;/ 日uint8 month = 9;/月uint16 year = 2013;/年char week1 = 1;/闹钟星期 char sec1 = 58;/闹钟秒char min1 = 50;/闹钟分char hour1 = 23;/闹钟时uint8 day1 = 30;/闹钟日uint8 month1 = 9;/闹钟月uint16 year1 = 2013;/闹钟年uint8 WeekData1;/闹钟星期标记uint8 number = 0;/定时uint8 WeekData;/星期标记uint8 speaker_num; /整点报时次数uint8 scan_key(void);/函数声名 /* 更新LCD时间分离读取 */void TimeChange()/时分秒timestr7 = sec%10+'0'timestr6 = sec/10+'0'timestr4 = min%10+'0'timestr3 = min/10+'0'timestr1 = hour%10+'0'timestr0 = hour/10+'0'/年月日daystr9 = day%10+'0'daystr8 = day/10+'0'daystr6 = month%10+'0'daystr5 = month/10+'0'daystr3 = year%10+'0'daystr2 = year/10%10+'0'daystr1 = year/100%10+'0'daystr0 = year/1000+'0'/星期WeekData = week+'0'/* 闹钟更新LCD时间分离读取 */void TimeChange1()/时分秒timestr17 = sec1%10+'0'timestr16 = sec1/10+'0'timestr14 = min1%10+'0'timestr13 = min1/10+'0'timestr11 = hour1%10+'0'timestr10 = hour1/10+'0'/年月日daystr19 = day1%10+'0'daystr18 = day1/10+'0'daystr16 = month1%10+'0'daystr15 = month1/10+'0'daystr13 = year1%10+'0'daystr12 = year1/10%10+'0'daystr11 = year1/100%10+'0'daystr10 = year1/1000+'0'/星期WeekData1 = week1+'0'/* 初始化系统定时器0 */void systimer0_init(void)TMOD |=0x01;/设置为1时用或(|)TMOD &=0xfd;/设置为0时用与(&) TH0 = 0xDC; / 定时10ms TL0 = 0x00;EA = 1;ET0=1; TR0=1;EX0 = 1;/* 闹钟时间设置 */void naozhong()uint8 number = 1;uint8 a = 0;uint8 b = 0;if(0 = key4)Delay1Ms(5);if(0 = key4)a = 1;LCD_write_command(0xc0+9);LCD_write_command(0x0f);while(!key4);while(a)if(0 = key4)Delay1Ms(5);if(0 = key4)a = 0;run = run;while(!key4); if(run)timestr9 = 'Y'elsetimestr9 = 'N'if(0 = key1)Delay1Ms(5);if(0 = key1)b = 1;while(!key1);while(b) if(0 = key1)Delay1Ms(5);if(0 = key1)number+;if(4 = number)b = 0;while(!key1);if(number = 1)LCD_write_command(0xc0+9);LCD_write_command(0x0f);if(number = 2)LCD_write_command(0xc0+6);LCD_write_command(0x0f);if(number = 3)LCD_write_command(0xc0+3);LCD_write_command(0x0f); switch(number) case 1: if(0 = key2) /闹钟秒加1的设置 Delay1Ms(5);if(0 = key2) sec1+; if(60 = sec1)sec1 = 0;while(!key2);timestr17 = sec1%10+'0'timestr16 = sec1/10+'0'LCD_write_char(8,1,timestr16);LCD_write_char(9,1,timestr17);LCD_write_command(0xc0+9); if(0 = key3) /闹钟秒减1的设置 Delay1Ms(5);if(0 = key3) sec1-; if(sec1 < 0)sec1 = 59;while(!key3);timestr17 = sec1%10+'0'timestr16 = sec1/10+'0'LCD_write_char(8,1,timestr16);LCD_write_char(9,1,timestr17);LCD_write_command(0xc0+9); break;case 2: if(0 = key2) /闹钟分加1的设置 Delay1Ms(5);if(0 = key2) min1+; if(60 = min1)min1 = 0;while(!key2);timestr14 = min1%10+'0'timestr13 = min1/10+'0'LCD_write_char(5,1,timestr13);LCD_write_char(6,1,timestr14);LCD_write_command(0xc0+6); if(0 = key3) /闹钟分减1的设置 Delay1Ms(5);if(0 = key3) min1-; if(min1 < 0)min1 = 59;while(!key3);timestr14 = min1%10+'0'timestr13 = min1/10+'0'LCD_write_char(5,1,timestr13);LCD_write_char(6,1,timestr14);LCD_write_command(0xc0+6); break;case 3: if(0 = key2) /闹钟时加1的设置 Delay1Ms(5);if(0 = key2) hour1+; if(24 = hour1)hour1 = 0;while(!key2);timestr11 = hour1%10+'0'timestr10 = hour1/10+'0'LCD_write_char(2,1,timestr10);LCD_write_char(3,1,timestr11);LCD_write_command(0xc0+3); if(0 = key3) /闹钟时减1的设置 Delay1Ms(5);if(0 = key3) hour1-; if(hour1 < 0)hour1 = 23;while(!key3);timestr11 = hour1%10+'0'timestr10 = hour1/10+'0'LCD_write_char(2,1,timestr10);LCD_write_char(3,1,timestr11);LCD_write_command(0xc0+3); break;case 4:b = 0;LCD_write_command(0x0c);break;LCD_write_command(0x0c);while(!key4);/* 判断按键进入时间调整 */uint8 scan_key(void)uint8 number = 1;uint8 a = 0;if(0 = key1)Delay1Ms(5);if(0 = key1)while(!key1);a = 1;LCD_write_command(0xc0+9);LCD_write_command(0x0f);while(a) if(0 = key1)Delay1Ms(5);if(0 = key1)number+;while(!key1);TR0 = 0;if(number = 2)LCD_write_command(0xc0+6);LCD_write_command(0x0f);if(number = 3)LCD_write_command(0xc0+3);LCD_write_command(0x0f);if(number = 4)LCD_write_command(0x80+11);LCD_write_command(0x0f);if(number = 5)LCD_write_command(0x80+8);LCD_write_command(0x0f);if(number = 6)LCD_write_command(0x80+5);LCD_write_command(0x0f);if(number = 7)LCD_write_command(0xc0+14);LCD_write_command(0x0f);if(8 = number)LCD_write_command(0x0c);a = 0;number = 0; switch(number) case 1: if(0 = key2) /秒加1的设置 Delay1Ms(5);if(0 = key2)sec+; if(60 = sec)sec = 0;timestr7 = sec%10+'0'timestr6 = sec/10+'0'LCD_write_char(8,1,timestr6);LCD_write_char(9,1,timestr7);LCD_write_command(0xc0+9);while(!key2); if(0 = key3) /秒减1的设置 Delay1Ms(5);if(0 = key3) sec-; if(sec < 0)sec = 59;timestr7 = sec%10+'0'timestr6 = sec/10+'0'LCD_write_char(8,1,timestr6);LCD_write_char(9,1,timestr7);LCD_write_command(0xc0+9);while(!key3); break;case 2: if(0 = key2) /分加1的设置 Delay1Ms(5);if(0 = key2) min+; if(60 = min)min = 0;timestr4 = min%10+'0'timestr3 = min/10+'0'LCD_write_char(5,1,timestr3);LCD_write_char(6,1,timestr4);LCD_write_command(0xc0+6);while(!key2); if(0 = key3) /分减1的设置 Delay1Ms(5);if(0 = key3) min-; if(min < 0)min = 59;timestr4 = min%10+'0'timestr3 = min/10+'0'LCD_write_char(5,1,timestr3);LCD_write_char(6,1,timestr4);LCD_write_command(0xc0+6);while(!key3); break;case 3: if(0 = key2) /时加1的设置 Delay1Ms(5);if(0 = key2) hour+;while(!key2); if(24 = hour)hour = 0;timestr1 = hour%10+'0'timestr0 = hour/10+'0'LCD_write_char(2,1,timestr0);LCD_write_char(3,1,timestr1);LCD_write_command(0xc0+3); if(0 = key3) /时减1的设置 Delay1Ms(5);if(0 = key3)while(!key3); hour-; if(hour < 0)hour = 23;timestr1 = hour%10+'0'timestr0 = hour/10+'0'LCD_write_char(2,1,timestr0);LCD_write_char(3,1,timestr1);LCD_write_command(0xc0+3); break;case 4: if(0 = key2) /日加1的设置 Delay1Ms(5);if(0 = key2)while(!key2);calculate = 1; if(calculate = 1)if(month=1|month=3|month=5|month=7|month=8|month=10|month=12)day+;if(day > 31)day=1; if(month=4|month=6|month=9|month=11) day+; if(day > 30)day=1; if(month = 2) cal_year = 1;while(cal_year = 1) leap_year = (year % 4 = 0 && year % 100 != 0)|(year % 400 = 0);cal_year = 0;if(leap_year=1) day+;if(day > 30)day=1; else day+;if(day > 29)day=1;calculate = 0;daystr9 = day%10+'0'daystr8 = day/10+'0'LCD_write_char(10,0,daystr8);LCD_write_char(11,0,daystr9);LCD_write_command(0x80+11); if(0 = key3) /日减1的设置 Delay1Ms(5);if(0 = key3)while(!key3);calculate = 1; if(calculate = 1)if(month=1|month=3|month=5|month=7|month=8|month=10|month=12)day-;if(day = 0)day=31; if(month=4|month=6|month=9|month=11) day-; if(day = 0)day=30; if(month = 2) cal_year = 1;while(cal_year = 1) leap_year = (year % 4 = 0 && year % 100 != 0)|(year % 400 = 0);cal_year = 0;if(leap_year=1) day-;if(day = 0)day=30; else day-;if(day = 0)day=29;calculate = 0;daystr9 = day%10+'0'daystr8 = day/10+'0'LCD_write_char(10,0,daystr8);LCD_write_char(11,0,daystr9);LCD_write_command(0x80+11); break;case 5: if(0 = key2) /月加1的设置 Delay1Ms(5);if(0 = key2)while(!key2); month+; if(13 = month)month = 1;daystr6 = month%10+'0'daystr5 = month/10+'0'LCD_write_char(7,0,daystr5);LCD_write_char(8,0,daystr6);LCD_write_command(0x80+8); if(0 = key3) /月减1的设置 Delay1Ms(5);if(0 = key3)while(!key3); month-; if(month = 0)