#include<reg52.h> //包含单片机寄存器的头文件 #include<intrins.h> //包含_nop_()函数定义的头文件 #define uchar unsigned char #define uint unsigned int sbit RS=P2^0; //寄存器选择位,将RS位定义为P2.0引脚 sbit RW=P2^1; //读写选择位,将RW位定义为P2.1引脚 sbit E=P2^2; //使能信号位,将E位定义为P2.2引脚 sbit BF=P0^7; //忙碌标志位,将BF位定义为P0.7引脚 uchar code table[]="2016-11-29 WEEK2"; //初始化液晶显示 16 uchar code table1[]="TIME: 12-34-56"; //14 uchar count,s1num; char second,minute,hour,day,month,year,week; sbit s1=P2^3; //功能键 sbit s2=P2^4; //加键 sbit s3=P2^5; //减键 sbit s4=P2^6; //保存并退出 /* 延时若干毫秒 */ void delay(uchar n) { uchar i,a,b; for(i=0;i<n;i++) for(b=199;b>0;b--) for(a=1;a>0;a--); } uchar BusyTest(void) { bit result; RS=0; //根据规定,RS为低电平,RW为高电平时,可以读状态 RW=1; E=1; //E=1,才允许读写 _nop_(); //空操作 _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 result=BF; //将忙碌标志电平赋给 E=0; //将E恢复低电平 return result; } void WriteInstruction(uchar dictate) { while(BusyTest()==1); //如果忙就等待 RS=0; //根据规定,RS和R/W同时为低电平时,可以写入指令 RW=0; E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,//就是让E从0到1发生正跳变,所以应先置"0" _nop_(); _nop_(); //空操作两个机器周期,给硬件反应时间 P0=dictate; //将数据送入P0口,即写入指令或地址 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 E=1; //E置高电平 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令 } void WriteData(uchar y) { while(BusyTest()==1); RS=1; //RS为高电平,RW为低电平时,可以写入数据 RW=0; E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,//就是让E从0到1发生正跳变,所以应先置"0" P0=y; //将数据送入P0口,即将数据写入液晶模块 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 E=1; //E置高电平 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令 } void LcdInitiate(void) { uchar num; second=56; minute=34; hour=12; week=6; day=7; month=12; year=13; count=0; s1num=0; E=0; delay(15); //延时15ms,首次写指令时应给LCD一段较长的反应时间 WriteInstruction(0x38); //显示模式设置:16×2显示,//5×7点阵,8位数据接口 delay(5);//延时5ms,给硬件一点反应时间 WriteInstruction(0x38); delay(5); WriteInstruction(0x38);//连续三次,确保初始化成功 delay(5); WriteInstruction(0x0c);//显示模式设置:显示开,无光标,//光标不闪烁 delay(5); WriteInstruction(0x06);//显示模式设置:光标右移,字符不移 delay(5); WriteInstruction(0x01);//清屏幕指令,将以前的显示内容清除 delay(5); WriteInstruction(0x80); for(num=0;num<16;num++)//让液晶显示日期 { WriteData(table[num]); delay(5); } WriteInstruction(0x80+0x40); for(num=0;num<14;num++)//让液晶显示时间 { WriteData(table1[num]); delay(5); } TMOD=0x01;//定时器中断初始化 TH0=(65536-50000)/256; TL0=(65536-50000)%256; EA=1; ET0=1; TR0=1; } void write_nyr(uchar add,uchar date) { uchar i,j; i=date/10; j=date%10; WriteInstruction(0x80+add); WriteData(0x30+i); WriteData(0x30+j); } void write_sfm(uchar add,uchar date) { uchar i,j; i=date/10; j=date%10; WriteInstruction(0x80+0x40+add); WriteData(0x30+i); WriteData(0x30+j); } void write_week(uchar add,uchar date) { WriteInstruction(0x80+add); WriteData(0x30+date); } bit leap_year() { int leap; if((year%4==0&&year%100!=0)||year%400==0) leap=1;//是闰年 else leap=0;//非闰年 return leap; } void keyscan() { if(s1==0) //第一个键是否按下 { delay(5); if(s1==0) { while(!s1); s1num++; if(s1num>7) s1num=1; if(s1num==1)//第一个键被按一次 { TR0=0; WriteInstruction(0x80+0x40+13); WriteInstruction(0x0f); } if(s1num==2) { WriteInstruction(0x80+0x40+10); } if(s1num==3) { WriteInstruction(0x80+0x40+7); } if(s1num==4) { WriteInstruction(0x80+9); } if(s1num==5) { WriteInstruction(0x80+6); } if(s1num==6) { WriteInstruction(0x80+3); } if(s1num==7) { WriteInstruction(0x80+15); } } } if(s1num!=0) //如果功能键被按下 { if(s2==0) //第二个按下 { delay(5); if(s2==0) { while(!s2); if(s1num==1) //第一个键被按一次,秒钟加一 { second++; if(second==60) second=0; write_sfm(12,second); WriteInstruction(0x80+0x40+13); } if(s1num==2) //第一个键被按二次,分钟加一 { minute++; if(minute==60) minute=0; write_sfm(9,minute); WriteInstruction(0x80+0x40+10); } if(s1num==3) //第一个键被按三次,时钟加一 { hour++; if(hour==24) hour=0; write_sfm(6,hour); WriteInstruction(0x80+0x40+7); } if(s1num==4) //第一个键被按四次,日期加一 { day++; if(day==32) day=1; write_nyr(8,day); WriteInstruction(0x80+9); } if(s1num==5) //第一个键被按五次,月加一 { month++; if(month==13) month=1; write_nyr(5,month); WriteInstruction(0x80+6); } if(s1num==6) //年加一 { year++; if(year==99) year=0; write_nyr(2,year); WriteInstruction(0x80+3); } if(s1num==7) //星期加一 { week++; if(week==8) week=1; write_week(15,week); WriteInstruction(0x80+15); } } } if(s3==0) //第三个键被按下 { delay(5); if(s3==0) { while(!s3); if(s1num==1)//秒减一 { second--; if(second==-1) second=59; write_sfm(12,second); WriteInstruction(0x80+0x40+13); } if(s1num==2) //分减一 { minute--; if(minute==-1) minute=59; write_sfm(9,minute); WriteInstruction(0x80+0x40+10); } if(s1num==3) //时减一 { hour--; if(hour==-1) hour=23; write_sfm(6,hour); WriteInstruction(0x80+0x40+7); } if(s1num==4) //日减一 { day--; if(day==0) day=31; write_nyr(8,day); WriteInstruction(0x80+9); } if(s1num==5) //月减一 { month--; if(month==0) month=12; write_nyr(5,month); WriteInstruction(0x80+6); } if(s1num==6) //年减一 { year--; if(year==-1) year=99; write_nyr(2,year); WriteInstruction(0x80+3); } if(s1num==7) //日期减一 { week--; if(week==0) week=7; write_week(15,week); WriteInstruction(0x80+15); } } } if(s4==0) //保存并退出 { s1num=0; WriteInstruction(0x0c); TR0=1; } } } void main(void) { uchar k=0; LcdInitiate(); //调用LCD初始化函数 while(1) { keyscan(); k=1; } } void timer0() interrupt 1 { count++; if(count==13) { count=0; second++; if(second==60) //秒计满60,秒归0,分+1 { second=0; minute++; if(minute==60) //分计满60,分归0,时+1 { minute=0; hour++; if(hour==24) //时计满24,时归0,星期+1,日+1 { hour=0; week++; day++; if(week==8) week=1; //星期计满7,星期归1 if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)//大月三十一天 { if(day==32) //大月天数计满31,日归1,月+1 { day=1; month++; } } if(month==4||month==6||month==9||month==11) //小月三十天 { if(day==31) //小月天数计满30,日归1,月+1 { day=1; month++; } } if(month==2) { if(leap_year()) { if(day==30) //闰年二月29天计满,日归1,月+1 { day=1; month++; } } else { if(day==29) //非闰年二月28天计满,日归1,月+1 { day=1; month++; } } } if(month==13) //月计满12,月归1,年+1 { month=1; year++; if(year==99) //年计满99,年归0 { year=0; } write_nyr(2,year); } write_nyr(5,month); } write_nyr(8,day); write_week(15,week); } write_sfm(6,hour); } write_sfm(9,minute); } write_sfm(12,second); }
|