基于51单片机LCD1602数字时钟演示ppt
- 格式:ppt
- 大小:826.50 KB
- 文档页数:7
20世纪末,电子技术获得了飞速的发展,在其推动下,现代电子产品几乎渗透了社会的各个领域,有力地推动了社会生产力的发展和社会信息化程度的提高,同时也使现代电子产品性能进一步提高,产品更新换代的节奏也越来越快。
时间对人们来说总是那么宝贵,工作的忙碌性和繁杂性容易使人忘记当前的时间。
忘记了要做的事情,当事情不是很重要的时候,这种遗忘无伤大雅。
但是,一旦重要事情,一时的耽误可能酿成大祸。
目前,单片机正朝着高性能和多品种方向发展趋势将是进一步向着CMOS化、低功耗、小体积、大容量、高性能、低价格和外围电路内装化等几个方面发展。
下面是单片机的主要发展趋势。
单片机应用的重要意义还在于,它从根本上改变了传统的控制系统设计思想和设计方法。
从前必须由模拟电路或数字电路实现的大部分功能,现在已能用单片机通过软件方法来实现了。
这种软件代替硬件的控制技术也称为微控制技术,是传统控制技术的一次革命。
纵观自己所处的这个快速发展的信息时代,数字电路的技术已广泛应用于各个领域中,它们无处不在我们的身边,我们通常所使用的手机,数码相机,MP3,MP4等电子产品都关联到数字电路的应用,而我想从自己所学专业的某一点出发,来分析数字电路在生活中的广泛应用。
由于时间在日常生活中的重要性,所以以时间为媒介的电子钟就被选为我这次论文选题的目标。
单片机简介单片微型计算机简称单片机,是典型的嵌入式微控制器(Microcontroller Unit),常用英文字母的缩写MCU表示单片机,它最早是被用在工业控制领域。
单片机由芯片内仅有CPU的专用处理器发展而来。
最早的设计理念是通过将大量外围设备和CPU集成在一个芯片中,使计算机系统更小,更容易集成进复杂的而对体积要求严格的控制设备当中。
INTEL的Z80是最早按照这种思想设计出的处理器,从此以后,单片机和专用处理器的发展便分道扬镳。
单片机又称单片微控制器,它不是完成某一个逻辑功能的芯片,而是把一个计算机系统集成到一个芯片上。
1 课设所需软件简介1.1 Keil uVision4的简要介绍2009年2月发布Keil μVision4,Keil μVision4引入灵活的窗口管理系统,使开发人员能够使用多台监视器,并提供了视觉上的表面对窗口位置的完全控制的任何地方。
新的用户界面可以更好地利用屏幕空间和更有效地组织多个窗口,提供一个整洁,高效的环境来开发应用程序。
新版本支持更多最新的ARM芯片,还添加了一些其他新功能。
2011年3月ARM公司发布最新集成开发环境RealView MDK开发工具中集成了最新版本的Keil uVision4,其编译器、调试工具实现与ARM器件的最完美匹配。
Keil C51开发系统基本知识Keil C51开发系统基本知识1. 系统概述Keil C51软件提供丰富的库函数和功能强大的集成开发调试工具,全Windows界面。
另外重要的一点,只要看一下编译后生成的汇编代码,就能体会到Keil C51生成的目标代码效率非常之高,多数语句生成的汇编代码很紧凑,容易理解。
在开发大型软件时更能体现高级语言的优势。
下面详细介绍Keil C51开发系统各部分功能和使用。
2. Keil C51单片机软件开发系统的整体结构C51工具包的整体结构,uVision与Ishell分别是C51 for Windows和for Dos 的集成开发环境(IDE),可以完成编辑、编译、连接、调试、仿真等整个开发流程。
开发人员可用IDE本身或其它编辑器编辑C或汇编源文件。
然后分别由C51及C51编译器编译生成目标文件(.OBJ)。
目标文件可由LIB51创建生成库文件,也可以与库文件一起经L51连接定位生成绝对目标文件(.ABS)。
ABS文件由OH51转换成标准的Hex文件,以供调试器dScope51或tScope51使用进行源代码级调试,也可由仿真器使用直接对目标板进行调试,也可以直接写入程序存贮器如EPROM中。
使用独立的Keil仿真器时,注意事项:* 仿真器标配11.0592MHz的晶振,但用户可以在仿真器上的晶振插孔中换插其他频率的晶振。
#include<reg52.h>#define uint unsigned int#define uchar unsigned charsbit LCD_RS=P2^6; //复位端液晶sbit LCD_RW=P2^5; //写数据端液晶sbit LCD_EP=P2^7; //使能端液晶sbit key1=P2^0;//键盘1sbit key2=P2^1;//键盘2sbit key3=P2^2;//键盘3sbit key4=P2^3;//键盘4sbit Beep=P1^5;//蜂鸣器uint num;uchar keynum,keynum1,shi1,fen1,miao1,aa,nian,shi2,fen2,miao2; uchar code table[]="2013-07-24-3"; //设定开始显示的时间uchar code table1[]=" 15:57:00";uchar code table2[]="1234567"; //定义二维字符数组uchar miao=00;uchar fen=57;uchar shi=15;uchar yue=07;uchar ri=24;uchar week=3;uchar nian=2013;void delay(uint z)//延时{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void di(){Beep=1;delay(1000);Beep=0;}void write_com(uchar com)//写指令函数液晶{LCD_RS=0;LCD_RW=0;P0=com;delay(5);//E变为以有个时间LCD_EP=1;delay(5);//一个高脉冲LCD_EP=0;}void write_date(uchar date)//写数据函数液晶{LCD_RS=1;LCD_RW=0;P0=date;delay(5);//E变为yi有个时间LCD_EP=1;delay(5);//一个高脉冲LCD_EP=0;}void init()//初始化函数{TMOD=0x01;TH0=(65536-50000)/256;TL0=(65536-50000)%256;EA=1;ET0=1;TR0=1;LCD_EP=0;write_com(0x38);//显示模式write_com(0x0c);//打开显示,光标不开,不闪烁write_com(0x01);//清屏write_com(0x80);//数据指针初始化}void year(uchar date)//显示年{uchar bai,shi,ge;uint qian;qian=2;bai=0;shi=date%1000%100/10;ge=date%10;write_com(0x80);write_date(0x30+qian);write_date(0x30+bai);write_date(0x30+shi);write_date(0x30+ge);}void xianshi(uchar add,uchar date)//显示月,日,时,分,秒{uchar shi,ge;shi=date/10;ge=date%10;write_com(add+0x80);write_date(0x30+shi);write_date(0x30+ge);}void xingqi()//显示星期{write_com(0x8b);write_date(table2[week-1]);}void key(){if(key1==0){delay(5); //去抖延时if(key1==0) //确认按键1被按下,{keynum++;while(!key1);//松手检测}if(keynum==1)//按下一次{TR0=0; //关闭定时器0write_com(0x83);//光标跳到nian份write_com(0x0f);//开启光标显示,光标闪烁}if(keynum==2){write_com(0x86);//光标跳到yue}if(keynum==3){write_com(0x89);//光标跳到ri}if(keynum==4){write_com(0x8b);//光标跳到xingqi}if(keynum==5){write_com(0x80+0x44);//光标跳到时}if(keynum==6){write_com(0x80+0x47);//光标跳到分}if(keynum==7){write_com(0x80+0x4a); //光标跳到秒}if(keynum==8){ keynum=0; //退出调时间模式TR0=1; //开启定时器0write_com(0x0c); //关闭光标显示}}if(keynum) //当进入调时间模式时{if(key2==0) //2按键按下jia{delay(5); //去抖延时if(key2==0){if(keynum==1)//调nian{nian++;//2每按下一次if(nian==2099)nian=2000; //加满清0year(nian);write_com(0x83); //写完数据指针指向月份原来位置}if(keynum==2)//调月{yue++;//2每按下一次月份加1if(yue==13)yue=1; //加满清0xianshi(5,yue); //显示月份write_com(0x86); //写完数据指针指向月份原来位置}if(keynum==3)//调日{ ri++;if(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)//1,3,5,7,8,10,12月有31天if(ri==32)ri=1;//加满还原if(yue==4||yue==6||yue==9||yue==11)//4,6,9,11月有30天if(ri==31)ri=1;if(yue==2&&((nian%4==0&&nian%100!=0)||nian%400==0))//闰年2月有29天if(ri==30)ri=1;if(yue==2&&(nian%4!=0)||(nian%100==0&&nian%400!=0))//非闰年2月有28天if(ri==29)ri=1;xianshi(8,ri);write_com(0x89); //写完数据指针指向日原来位置}if(keynum==4)//调星期{week++; //2每按下一次星期加1if(week==7) //加满还原week=1;xingqi(); //显示星期write_com(0x8b); //写完数据指针指向星期原来位置}if(keynum==5)//调时{shi++;//2每按下一次时加1if(shi==24)shi=0; //加满还原xianshi(0x43,shi); //显示时write_com(0x80+0x44); //写完数据指针指向时原来位置}if(keynum==6)//调分{fen++;//2每按下一次分加1if(fen==60)fen=0;//加满还原xianshi(0x46,fen); //显示分write_com(0x80+0x47); //写完数据指针指向分原来位置}if(keynum==7)//调秒{miao++; //2每按下一次秒加1if(miao==60)miao=0;//加满还原xianshi(0x49,miao);//显示秒write_com(0x80+0x4a); //写完数据指针指向秒原来位置}while(!key2); //松手检测}}if(key3==0){delay(5);//消抖if(key3==0)//3按下时减1{if(keynum==1)//月减一{nian--;if(nian==-1)nian=2000;year(nian);write_com(0x83);}if(keynum==2)//月减一{yue--;if(yue==-1)yue=12;xianshi(5,yue);write_com(0x86);}if(keynum==3)//日减一{ri--;if(ri==0){if(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)//1,3,5,7,8,10,12ri=31;if(yue==4||yue==6||yue==9||yue==11)//4,6,9,11ri=30;if(yue==2&&((nian%4==0&&nian%100!=0)||nian%400==0))//闰年ri=29;if(yue==2&&(nian%4!=0)||(nian%100==0&&nian%400!=0))//非闰年ri=28;}xianshi(8,ri);write_com(0x89);}if(keynum==4)//星期减一{week--;if(week==-1)week=6;xingqi();write_com(0x8b);}if(keynum==5)//时减一{shi--;if(shi==-1)shi=23;xianshi(0x43,shi);write_com(0xc4);}if(keynum==6)//分减一{fen--;if(fen==-1)fen=59;xianshi(0x46,fen);write_com(0xc7);}if(keynum==7)//秒减一{miao--;if(miao==-1)miao=59;xianshi(0x49,miao);write_com(0xca);}while(!key3); //3松手检测}}}if(key4==0)//4被按下进入调闹钟模式{ delay(5);//消抖if(key4==0){keynum1++;while(!key4);//松手}if(keynum1==1){ write_com(0x01);//清屏,指针清0write_com(0x80+0x45);//在时分之间显示":"write_date(':');write_com(0x80+0x48);//在分秒之间显示":"write_date(':');write_com(0x0f);//开启光标write_com(0xc4);//光标指向时}if(keynum1==2){write_com(0xc7);//光标指向分}if(keynum1==3){write_com(0xca);//光标指向秒}if(keynum1==4){ xianshi(0x43,shi1);xianshi(0x46,fen1);xianshi(0x49,miao1);}if(keynum1==5){ keynum1=0;write_com(0x0c);//关闭光标}}if(keynum1)//进入了调闹钟模式{if(key2==0)//2按下加1{delay(5);if(key2==0)//确实按下{if(keynum1==1)//调闹钟的时{shi1++;if(shi1==24)shi1=0;xianshi(0x43,shi1);write_com(0xc4);}if(keynum1==2)//调闹钟de分{fen1++;if(fen1==60)fen1=0;xianshi(0x46,fen1);write_com(0xc7);}if(keynum1==3){miao1++;if(miao1==60)miao1=0;xianshi(0x49,miao1);write_com(0xca);}while(!key2);//松手检测}}if(key3==0)//3每按一次减1{delay(5);if(key3==0){if(keynum1==1){shi1--;if(shi1==-1)shi1=23;xianshi(0x43,shi1);write_com(0xc4);}if(keynum1==2){fen1--;if(fen1==-1)fen1=59;xianshi(0x46,fen1);write_com(0xc7);}if(keynum1==3){miao1--;if(miao1==-1)miao1=59;xianshi(0x49,miao1);write_com(0xca);}while(!key3);//松手检测}}}}void daole(){if(aa==19)//一秒到了{ aa=0; //清0miao++;}if(miao==60) //一分了{ miao=0;fen++; }if(!keynum1) xianshi(0x49,miao); //当调闹钟模式按下时不显示当前时间if(fen==60){ fen=0;shi++;}if(!keynum1){xianshi(0x46,fen);write_com(0x80+0x48);//在分秒之间显示":"write_date(':') ;} //当调闹钟模式按下时不显示当前时间if(shi==24){shi=0;ri++;week++;}if(!keynum1){xianshi(0x43,shi);write_com(0x80+0x45);//在时分之间显示":"write_date(':') ;} //当调闹钟模式按下时不显示当前时间if(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)if(ri==32){ri=1;yue++;}if(yue==4||yue==6||yue==9||yue==11)if(ri==31){ri=1;yue++;}if(yue==2&&((nian%4==0&&nian%100!=0)||nian%400==0))if(ri==30){ri=1;yue++;}if(yue==2&&(nian%4!=0)||(nian%100==0&&nian%400!=0))if(ri==29){ri=1;yue++;}if(!keynum1) xianshi(8,ri); //当调闹钟模式按下时不显示当前时间if(week==7)week=0;if(!keynum1) //当调闹钟模式按下时不显示当前时间{xingqi();write_com(0x8a);write_date('-');}if(yue==13){yue=0;nian++;}if(!keynum1) //当调闹钟模式按下时不显示当前时间{xianshi(5,yue);write_com(0x87);write_date('-');write_com(0x84);write_date('-');}if(!keynum1) //当调闹钟模式按下时不显示当前时间year(nian);}}void main(){init();for(num=0;num<12;num++){ write_date(table[num]);delay(5);} //显示初始时间write_com(0x80+0x40);for(num=0;num<11;num++){ write_date(table1[num]);delay(5);}TR0=1;while(1){if(shi==shi1&&fen==fen1&&miao==miao1) //闹钟到了蜂鸣器响{di();if(key4==0)//4被按下{ delay(5);//消抖if(key4==0)Beep=0;TR0=1;while(!key4);//松手}}daole();key();}}void time() interrupt 1 //中断函数{TH0=(65536-45872)/256;TL0=(65536-45872)%256;//进入中断装初值aa++;}。
基于stc51单片机的LCD1602显示时间的电子万年历(显示1.1 Keil uVision4的简要介绍2020年2月公布Keil μVision4,Keil μVision4引入灵活的窗口治理系统,使开发人员能够使用多台监视器,并提供了视觉上的表面对窗口位置的完全操纵的任何地点。
新的用户界面能够更好地利用屏幕空间和更有效地组织多个窗口,提供一个整洁,高效的环境来开发应用程序。
新版本支持更多最新的ARM芯片,还添加了一些其他新功能。
2020年3月ARM公司公布最新集成开发环境RealView MDK开发工具中集成了最新版本的Keil uVision4,其编译器、调试工具实现与ARM器件的最完美匹配。
Keil C51开发系统差不多知识Keil C51开发系统差不多知识1. 系统概述Keil C51软件提供丰富的库函数和功能强大的集成开发调试工具,全Windows界面。
另外重要的一点,只要看一下编译后生成的汇编代码,就能体会到Keil C51生成的目标代码效率专门之高,多数语句生成的汇编代码专门紧凑,容易明白得。
在开发大型软件时更能表达高级语言的优势。
下面详细介绍Keil C51开发系统各部分功能和使用。
2. Keil C51单片机软件开发系统的整体结构C51工具包的整体结构,uVision与Ishell分别是C51 for Windows和for Dos的集成开发环境(IDE),能够完成编辑、编译、连接、调试、仿真等整个开发流程。
开发人员可用IDE本身或其它编辑器编辑C或汇编源文件。
然后分别由C51及C51编译器编译生成目标文件(.OBJ)。
目标文件可由LIB51创建生成库文件,也能够与库文件一起经L51连接定位生成绝对目标文件(.ABS)。
ABS文件由OH51转换成标准的Hex文件,以供调试器dScope51或tScope51使用进行源代码级调试,也可由仿真器使用直截了当对目标板进行调试,也能够直截了当写入程序存贮器如EPROM中。
用51单片机和1602液晶做的数字钟数字钟是人们日常生活中常见的时间显示设备,它能够精确显示当前的时间,并且兼具简约和实用性。
本文将介绍使用51单片机和1602液晶屏幕制作自己的数字钟的方法。
所需材料在开始制作之前,我们需要准备以下材料: - 51单片机开发板 - 1602液晶屏幕 - 数字时钟芯片RTC(Real-Time Clock) - 面包板和导线 - 电阻和电容 - 编程器和烧录器硬件连接首先,我们需要将51单片机、1602液晶屏幕和RTC芯片连接起来。
根据硬件接口的定义和引脚功能的规定,我们可以进行以下连接: - 将51单片机的VCC 引脚连接到1602液晶屏幕的VCC引脚,用于提供电源。
- 将51单片机的GND引脚连接到1602液晶屏幕的GND引脚,用于地线连接。
- 将51单片机的P0口连接到1602液晶屏幕的数据线D0-D7,用于数据传输。
- 将51单片机的P2口连接到1602液晶屏幕的RS引脚,用于选择数据和命令传输。
- 将51单片机的P3口连接到1602液晶屏幕的EN引脚,用于启用LCD。
此外,还需要将RTC芯片连接到51单片机上,以实现时间的准确显示。
具体的连接方式可以参考RTC芯片的规格说明书。
软件编程完成硬件连接后,我们需要进行软件编程,以便控制51单片机、1602液晶屏幕和RTC芯片的功能。
初始化首先,我们需要对51单片机和1602液晶屏幕进行初始化设置。
这包括设置引脚的功能模式、初始化1602液晶屏幕的显示模式和清空显示区域。
读取时间接下来,我们需要通过RTC芯片来读取当前的时间。
这通常包括读取RTC芯片存储的年、月、日、时、分和秒的数据。
显示时间读取时间后,我们可以将其显示在1602液晶屏幕上。
这可以通过更新特定的LCD显示区域来实现。
我们可以在指定的位置、特定的行和列上显示时间。
更新时间为了实现实时的时间显示,我们需要定期更新显示的时间。
可以使用定时器中断来定期更新时间,并根据需要刷新液晶屏幕上的显示。
/*功能:52单片机定时器0电子表LCD1602显示可对时间进行调节作者:燕山大学里仁学院09应电四班杨立业欢迎您的建议、指点和更多交流QQ:1024549573晶振:12M*/#include<reg52.h>#define uint unsigned intsbit lcden=P3^4; //液晶的使能端sbit rs=P3^5; //液晶的数据指令控制端sbit wr=P3^6; //液晶的读写端sbit rd=P3^7; //按键的一个线选使按键共阴极sbit fc=P3^0; //功能键确定时间调整的位置sbit jia=P3^1; //加1sbit jian=P3^2;//减1unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f};unsigned char code table1[]=" 00:00:00 ";uint num,num1,i,shi,ge,shu;long int hour,fen,miao;void write_com(uint com);void write_date(uint date);void init1602();void init() ;void write_sf(uint add,uint sf);void delay(uint x);void keyscan();void main(){ init();init1602();write_com(0x80+0x40+3);for(num1=1;num1<8;num1++){ write_date(table1[num1]);delay(5);}while(1){ keyscan();}}void write_com(uint com)//1602 写指令{ rs=0;P0=com;lcden=0;delay(10);lcden=1;delay(10);lcden=0;}void write_date(uint date)//1602写数据{ rs=1;P0=date;lcden=0;delay(10);lcden=1;delay(10);lcden=0;}void init() //定时器初始化{ rd=0;TMOD=0X01;TH0=(65536-50000)/256;TL0=(65536-50000)%256;EA=1;ET0=1;TR0=1;}void init1602()//1602初始化{ dula=0;wela=0;wr=0;lcden=0;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);}void write_sf(uint add,uint sf)//显示时间{ uint shi,ge;shi=sf/10;ge=sf%10;write_com(0x80+0x40+add);write_date(0x30+shi);write_date(0x30+ge);}void time0() interrupt 1 //定时器0中断{ TH0=(65536-50000)/256;TL0=(65536-50000)%256;num++;if(num==20){num=0;miao++;if(miao==60){ miao=0;fen++;if(fen==60){ fen=0;hour++;if(hour==24)hour=0;write_sf(4,hour);}write_sf(7,fen);}write_sf(10,miao);}}void delay(uint x)//ms级延时{ uint i,j;for(i=x;i>0;i--)for(j=110;j>0;j--);}void keyscan()//按键扫描{ if(fc==0) //功能键选择时间调节加减的位置{ delay(5);if(fc==0){ while(!fc);shu++;if(shu==4)shu=0;switch(shu){ case 0:TR0=1;write_com(0x0c);break;case 1:TR0=0;write_com(0x80+0x40+11);write_com(0x0f);break;case 2:write_com(0x80+0x40+8);write_com(0x0f);break;case 3:write_com(0x80+0x40+5);write_com(0x0f);break;}}}if(jia==0) //时或分或秒的加一{ delay(5);if(jia==0){ while(!jia);switch(shu){ case 1: miao++;if(miao==60)miao=0;write_sf(10,miao);write_com(0x80+0x40+11);break;case 2: fen++;if(fen==60)fen=0;write_sf(7,fen);write_com(0x80+0x40+8);break;case 3: hour++;if(hour==24)hour=0;write_sf(4,hour);write_com(0x80+0x40+5);break;}}}if(jian==0) //时或分或秒的减一{ delay(8);if(jian==0){ while(!jian);switch(shu){ case 1: --miao;if(miao==-1)miao=59;write_sf(10,miao);write_com(0x80+0x40+11);break;case 2: fen--;if(fen==-1)fen=59;write_sf(7,fen);write_com(0x80+0x40+8);break;case 3: hour--;if(hour==-1)hour=23;write_sf(4,hour);write_com(0x80+0x40+5);break;}}}}。
用LCD1602 显示的时钟2012-04-30 15:04有这样一个题目:求一个为51 单片机编写的LCD 电子时钟的设计,简单就好!希望说一下怎么设计这个时钟,都需要些什么东西,最重要的——把这个设计需要的程序写出来。
设计的任务:以单片机控制的时钟,在LCD 显示器上显示当前的时间。
设计的基本要求:1.使用文字型LCD 显示器显示当前时间。
2.显示格式为“时时:分分:秒秒”。
3.用4个功能键操作来设置当前时间。
各个功能键的功能如下:K1:进入设置现在的时间。
K2:设置小时。
K3:设置分钟。
K4:确认完成设置。
4. 程序执行后工作指示灯LED 闪烁,表示程序开始执行,LCD 显示“00:00:00”,然后开始计时。
题目链接:/question/416705477.html//==================================================提到设计时钟,很多人都想到了时钟芯片DS1302,都说它简单、准确。
其实,这是个误区。
仅仅使用一般的单片机,简单的编程,达到相同DS1302 的准确度,并不是难事。
如果不要求计算平闰年、不要求分清大小月、不要求计算星期几,只是要求一个简单的时钟(及日历),用DS1302,就是自寻烦恼。
大家可以打开题目链接,看看其中的一些答案,就可以看出使用DS1302 是多么的繁琐了,简直就是一场噩梦。
做而论道以前就使用普通的单片机和LCD1602 设计过《时钟与日历》,程序设计的非常合理,时间精度就完全取决于晶振的精度。
设计出来的时钟,几个月都差不上一秒。
针对这个题目,做而论道翻出了以前的设计,删节了一些不需要的功能,设计出了符合题目要求的时钟,用PROTEUS 仿真截图如下:程序用C 语言编写,全部代码如下://---------------------------------------------------#include<reg52.h>#define uchar unsigned char#define uint unsigned int#define KEY_IO P3#define LCD_IO P0sbit LCD_RS = P2^0;sbit LCD_RW = P2^1;sbit LCD_EN = P2^2;sbit SPK = P1^2;sbit LED = P2^4;bit new_s, modify = 0;char t0, sec = 50, min = 59, hour = 23;char code LCD_line1[] = "Designed by ZELD"; char code LCD_line2[] = "Timer: 00:00:00 "; char Timer_buf[] = "23:59:50";//---------------------------------------------------void delay(uint z){uint x, y;for(x = z; x > 0; x--) for(y = 100; y > 0; y--);//---------------------------------------------------void W_LCD_Com(uchar com) //写指令{LCD_RS = 0; LCD_IO = com; // LCD_RS和R/W都为低电平时,写入指令LCD_EN = 1; delay(5); LCD_EN = 0; //用EN输入一个高脉冲}//---------------------------------------------------void W_LCD_Dat(uchar dat) //写数据{LCD_RS = 1; LCD_IO = dat; // LCD_RS为高、R/W为低时,写入数据LCD_EN = 1; delay(5); LCD_EN = 0; //用EN输入一个高脉冲}//---------------------------------------------------void W_LCD_STR(uchar *s) //写字符串{while(*s) W_LCD_Dat(*s++);}//---------------------------------------------------void W_BUFF(void) //填写显示缓冲区{Timer_buf[7] = sec % 10 + 48; Timer_buf[6] = sec / 10 + 48;Timer_buf[4] = min % 10 + 48; Timer_buf[3] = min / 10 + 48;Timer_buf[1] = hour % 10 + 48;Timer_buf[0] = hour / 10 + 48;W_LCD_Com(0xc0 + 7); W_LCD_STR(Timer_buf);}//---------------------------------------------------uchar read_key(void){uchar x1, x2;KEY_IO = 255;x1 = KEY_IO;if (x1 != 255) {delay(100);x2 = KEY_IO;if (x1 != x2) return 255;while(x2 != 255) x2 = KEY_IO;if (x1 == 0x7f) return 0;else if (x1 == 0xbf) return 1;else if (x1 == 0xdf) return 2;else if (x1 == 0xef) return 3;else if (x1 == 0xf7) return 4;}return 255;//---------------------------------------------------void Init(){LCD_RW = 0;W_LCD_Com(0x38); delay(50);W_LCD_Com(0x0c);W_LCD_Com(0x06);W_LCD_Com(0x01);W_LCD_Com(0x80); W_LCD_STR(LCD_line1);W_LCD_Com(0xC0); W_LCD_STR(LCD_line2);TMOD = 0x01; //T0定时方式1TH0 = 0x4c;TR0 = 1; //启动T0PT0 = 1; //高优先级, 以保证定时精度ET0 = 1;EA = 1;}//---------------------------------------------------void main(){uint i, j;uchar Key;Init();while(1) {//-------------------------------if (new_s) { //如果出现了新的一秒, 修改时间new_s = 0; sec++; sec %= 60;if(!sec) { min++; min %= 60;if(!min) { hour++; hour %= 24;}}W_BUFF(); //写显示//-------------------------------if (!sec && !min) { //整点报时for (i = 0; i < 200; i++) {SPK = 0; for (j = 0; j < 100; j++);SPK = 1; for (j = 0; j < 100; j++);} }}//-------------------------------Key = read_key(); //读出按键switch(Key) { //分别处理四个按键case 0: modify = 1; break;case 1: if(modify) {min++; min %= 60; W_BUFF(); break;}case 2: if(modify) {hour++; hour %= 24; W_BUFF(); break;}case 3: modify = 0; break;} }}//---------------------------------------------------void timer0(void) interrupt 1 //T0中断函数, 50ms执行一次{TH0 = 0x4c;t0++; t0 %= 20; //20, 一秒钟if(t0 == 0) {new_s = 1; LED = ~LED;}if(modify) LED = 0;}//===================================================呵呵,全部程序,也不过120 行左右。