#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); }
|