長春工業(yè)大學 測控技術與儀器專業(yè) 單片機LCD1602顯示年月日時鐘帶星期和鬧鐘,可識別閏年 下載文檔即可完全復制 #include <reg52.h> #define uchar unsigned char #define uint unsigned int sbit lcdrs =P0^7; //液晶引腳定義 sbit led_cs = P0^6; sbit lcden =P0^5; sbit boom =P3^6; sbit key1 = P3^5; sbit key2 = P3^4; sbit key3 = P3^3; sbit keyE = P3^2; ucharnum,key1num,key2num,count,hour,min,sec,day,mon,year,shi,fen,miao,week; char ye1,ye2; uchar code cg_1602[]={0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02, 0x0f,0x09,0x0f,0x09,0x0f,0x09,0x11,0x00, 0x0f,0x09,0x09,0x0f,0x09,0x09,0x0f,0x00, 0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02,};//"年月日" /*延時函數*/ void delay(uint xms) { uint i,j; for(i=xms;i>0;i--) for(j=114;j>0;j--); } /*1602液晶*/ void write_com(uchar com)//寫命令 { lcdrs=0; lcden=0; P0=com; delay(5); lcden=1; delay(5); lcden=0; } void write_data(uchar date)//寫數據 { lcdrs=1; lcden=0; P0=date; delay(5); lcden=1; delay(5); lcden=0; } void write_by_xy(uchar x,uchar y)//坐標定位 { ucharaddress; if(y==0) address=0x80+x;//y=0,寫第一行 else address=0xc0+x;//y=1,寫第二行 write_com(address); } /*void write_char(uchar x,uchar y,uchar date)//坐標定位顯示 { write_by_xy(x,y);//先定位 write_data(date);//后寫數 }*/ void write_string(uchar x,uchar y,uchar *s)//寫字符串 { write_by_xy(x,y);//設定顯示位置 while(*s)//writecharacter { P0=*s; write_data(*s); s++; } } void write_sfm(uchar add,uchar date)//寫時分秒函數 { ucharhour,ge; hour=date/10;//分解一個2位數的十位和個位 ge=date%10; write_com(0x80+add);//設置顯示位置 write_data(0x30+hour);//送去液晶顯示十位 write_data(0x30+ge);//送去液晶顯示個位 } void write_cg()//寫入固定漢字和符號 { write_com(0x40);//設定CGRAM地址 for(num=0;num<24;num++)//將自定義字型碼寫入CGRAM中 { write_data(cg_1602[num]); } write_com(0xc4);//年 { write_data(0); } write_com(0xc7);//月 { write_data(1); } write_com(0xca);//日 { write_data(2); } write_string(2,0,":"); write_string(5,0,":"); write_string(0x0a,0,":"); write_string(0x0d,0,":"); write_string(0x0c,1,"W"); write_string(0x0d,1,"K"); } void init_1602()//初始化 { led_cs=0; hour=23;min=59;sec=55;key1num=0;count=0;day=28;mon=2;ye1=20;ye2=13;year=ye1*100+ye2;boom=0;shi=0;fen=0;miao=0;week=7; write_com(0x38); write_com(0x0c); write_com(0x06); write_com(0x01); write_string(0,1,"2013"); write_string(5,1,"02"); write_string(8,1,"28"); write_sfm(8,shi); write_sfm(0x0b,fen); write_sfm(0x0e,miao); write_sfm(0,hour); write_sfm(3,min); write_sfm(6,sec); write_sfm(0x48,day); write_sfm(0x45,mon); write_sfm(0x40,ye1); write_sfm(0x42,ye2); write_sfm(0x4e,week); write_cg(); TMOD=0x01;//設置定時器0工作模式1 TH0=(65536-50000)/256;//定時器裝初值 TL0=(65536-50000)%256; EA=1; //開總中斷 ET0=1; //開定時器0中斷 TR0=1; //啟動定時器0 } /*鍵盤掃描函數*/ void keyscan()//按鍵掃描函數 { //keyE =0; if(key1==0) { delay(5); if(key1==0)//確認功能鍵被按下 { key1num++;//功能鍵按下次數記錄 while(!key1);//釋放確認 if(key1num==1)//第一次被按下時 { TR0=0;//關閉定時器 write_com(0x80+7);//光標定位到秒位置 write_com(0x0f);//光標開始閃爍 } if(key1num==2)//第二次按下光標閃爍定位到分鐘位置 { write_com(0x80+4); } if(key1num==3)//第三次按下光標閃爍定位到小時位置 { write_com(0x80+1); } if(key1num==4)//第四次按下光標閃爍定位到日位置 { write_com(0x80+0x49); } if(key1num==5)//第五次按下光標閃爍定位到月位置 { write_com(0x80+0x46); } if(key1num==6)//第六次按下光標閃爍定位到年2位置 { write_com(0x80+0x43); } if(key1num==7)//第七次按下光標閃爍定位到年1位置 { write_com(0x80+0x41); } if(key1num==8)//第八次按下光標閃爍定位到星期位置 { write_com(0x80+0x4f); } if(key1num==9)//第九次按下 { key1num=0;//記錄按鍵數清零 write_com(0x0c);//取消光標閃爍 TR0=1;//啟動定時器使時鐘開始走 } } } if(key1num!=0)//只有功能鍵被按下后,增加和減小鍵才有效 { if(key2==0) { delay(5); if(key2==0)//增加鍵確認被按下 { while(!key2);//按鍵釋放 if(key1num==1)//若功能鍵第一次按下 { sec++;//則調整秒加1 if(sec==60)//若滿60后將清零 sec=0; write_sfm(6,sec);//每調節(jié)一次送液晶顯示一下 write_com(0x80+7);//顯示位置重新回到調節(jié)處 } if(key1num==2)//若功能鍵第二次按下 { min++;//則調整分鐘加1 if(min==60)//若滿60后將清零 min=0; write_sfm(3,min);//每調節(jié)一次送液晶顯示一下 write_com(0x80+4);//顯示位置重新回到調節(jié)處 } if(key1num==3)//若功能鍵第三次按下 { hour++;//則調整小時加1 if(hour==24)//若滿24后將清零 hour=0; write_sfm(0,hour);;//每調節(jié)一次送液晶顯示一下 write_com(0x80+1);//顯示位置重新回到調節(jié)處 } if(key1num==4)//若功能鍵第四次按下 { day++;//則調整日加1 if(day>31)//若大于31后將置一 day=1; write_sfm(0x48,day);//每調節(jié)一次送液晶顯示一下 write_com(0x80+0x48);//顯示位置重新回到調節(jié)處 } if(key1num==5)//若功能鍵第五次按下 { mon++;//則調整月加1 if(mon>12)//若大于12后將置一 mon=1; write_sfm(0x45,mon);//每調節(jié)一次送液晶顯示一下 write_com(0x80+0x45);//顯示位置重新回到調節(jié)處 } if(key1num==6)//若功能鍵第六次按下 { ye2++;//則調整年加1 if(ye2==0x0a)//若滿99后將清零 ye2=0; year=ye1*100+ye2; write_sfm(0x42,ye2);//每調節(jié)一次送液晶顯示一下 write_com(0x80+0x42);//顯示位置重新回到調節(jié)處 } if(key1num==7)//若功能鍵第七次按下 { ye1++;//則調整年加100 if(ye1==0x0a)//若滿99后將清零 ye1=0; year=ye1*100+ye2; write_sfm(0x40,ye1);//每調節(jié)一次送液晶顯示一下 write_com(0x80+0x40);//顯示位置重新回到調節(jié)處 } if(key1num==8)//若功能鍵第八次按下 { week++;//則調整周加一 if(week>7)//若大于7后置一 week=1; write_sfm(0x4f,week);//每調節(jié)一次送液晶顯示一下 write_com(0x80+0x4f);//顯示位置重新回到調節(jié)處 } } } if(key3==0) { delay(5); if(key3==0)//確認減小鍵被按下 { while(!key3);//按鍵釋放 if(key1num==1)//若功能鍵第一次按下 { sec--;//則調整秒減1 if(sec==-1)//若減到負數則將其重新設置為59 sec=59; write_sfm(6,sec);//每調節(jié)一次送液晶顯示一下 write_com(0x80+7);//顯示位置重新回到調節(jié)處 } if(key1num==2)//若功能鍵第二次按下 { min--;//則調整分鐘減1 if(min==-1)//若減到負數則將其重新設置為59 min=59; write_sfm(3,min);//每調節(jié)一次送液晶顯示一下 write_com(0x80+4);//顯示位置重新回到調節(jié)處 } if(key1num==3)//若功能鍵第三次按下 { hour--;//則調整小時減1 if(hour==-1)//若減到負數則將其重新設置為23 hour=23; write_sfm(0,hour);//每調節(jié)一次送液晶顯示一下 write_com(0x80+1);//顯示位置重新回到調節(jié)處 } if(key1num==4)//若功能鍵第四次按下 { day--;//則調整日減1 if(day==0)//若日為零時將置一 day=31; write_sfm(0x48,day);//每調節(jié)一次送液晶顯示一下 write_com(0x80+0x49);//顯示位置重新回到調節(jié)處 } if(key1num==5)//若功能鍵第五次按下 { mon--;//則調整月減1 if(mon==0)//若月為零將置一 mon=12; write_sfm(0x45,mon);//每調節(jié)一次送液晶顯示一下 write_com(0x80+0x45);//顯示位置重新回到調節(jié)處 } if(key1num==6)//若功能鍵第六次按下 { ye2--;//則調整年減1 if(ye2<0)//若小于零后將設置為99 ye2=99; year=ye1*100+ye2; write_sfm(0x42,ye2);//每調節(jié)一次送液晶顯示一下 write_com(0x80+0x42);//顯示位置重新回到調節(jié)處 } if(key1num==7)//若功能鍵第七次按下 { ye1--;//則調整年減100 if(ye1<0)//若小于零后將設置為99 ye1=99; year=ye1*100+ye2; write_sfm(0x40,ye1);//每調節(jié)一次送液晶顯示一下 write_com(0x80+0x40);//顯示位置重新回到調節(jié)處 } if(key1num==8)//若功能鍵第八次按下 { week--;//則調整周減一 if(week==0)//若等于0后將置7 week=7; write_sfm(0x4f,week);//每調節(jié)一次送液晶顯示一下 write_com(0x80+0x4f);//顯示位置重新回到調節(jié)處 } } } } if(keyE==0) { delay(5); if(keyE==0)//確認功能鍵被按下 { key2num++;//功能鍵按下次數記錄 while(!keyE);//釋放確認 if(key2num==1)//第一次被按下時 { TR0=0;//關閉定時器 write_com(0x80+0x0f);//光標定位到秒位置 write_com(0x0f);//光標開始閃爍 } if(key2num==2)//第二次按下光標閃爍定位到分鐘位置 { write_com(0x80+0x0c); } if(key2num==3)//第三次按下光標閃爍定位到小時位置 { write_com(0x80+9); } if(key2num==4)//第八次按下 { key2num=0;//記錄按鍵數清零 write_com(0x0c);//取消光標閃爍 TR0=1;//啟動定時器使時鐘開始走 } } } if(key2num!=0)//只有功能鍵被按下后,增加和減小鍵才有效 { if(key2==0) { delay(5); if(key2==0)//增加鍵確認被按下 { while(!key2);//按鍵釋放 if(key2num==1)//若功能鍵第一次按下 { miao++;//則調整秒加1 if(miao==60)//若滿60后將清零 miao=0; write_sfm(0x0e,miao);//每調節(jié)一次送液晶顯示一下 write_com(0x80+0x0e);//顯示位置重新回到調節(jié)處 } if(key2num==2)//若功能鍵第二次按下 { fen++;//則調整分鐘加1 if(fen==60)//若滿60后將清零 fen=0; write_sfm(0x0b,fen);//每調節(jié)一次送液晶顯示一下 write_com(0x80+0x0b);//顯示位置重新回到調節(jié)處 } if(key2num==3)//若功能鍵第三次按下 { shi++;//則調整小時加1 if(shi==24)//若滿24后將清零 shi=0; write_sfm(8,shi);;//每調節(jié)一次送液晶顯示一下 write_com(0x80+8);//顯示位置重新回到調節(jié)處 } } } if(key3==0) { delay(5); if(key3==0)//確認減小鍵被按下 { while(!key3);//按鍵釋放 if(key2num==1)//若功能鍵第一次按下 { miao--;//則調整秒減1 if(miao==-1)//若減到負數則將其重新設置為59 miao=59; write_sfm(0x0e,miao);//每調節(jié)一次送液晶顯示一下 write_com(0x80+0x0e);//顯示位置重新回到調節(jié)處 } if(key2num==2)//若功能鍵第二次按下 { fen--;//則調整分鐘減1 if(fen==-1)//若減到負數則將其重新設置為59 fen=59; write_sfm(0x0b,fen);//每調節(jié)一次送液晶顯示一下 write_com(0x80+0x0b);//顯示位置重新回到調節(jié)處 } if(key2num==3)//若功能鍵第三次按下 { shi--;//則調整小時減1 if(shi==-1)//若減到負數則將其重新設置為23 shi=23; write_sfm(8,shi);//每調節(jié)一次送液晶顯示一下 write_com(0x80+8);//顯示位置重新回到調節(jié)處 } } } } } /*主函數*/ void main() { led_cs=0; init_1602(); while(1) { keyscan(); } } /*中斷函數*/ void timer0() interrupt 1//定時器0中斷服務程序 { TH0=(65536-50000)/256;//再次裝定時器初值 TL0=(65536-50000)%256; count++;//中斷次數累加 if(count==20)//20次50毫秒為1秒 { count=0; sec++; if(sec==60)//秒加到60則進位分鐘 { sec=0;//同時秒數清零 min++; if(min==60)//分鐘加到60則進位小時 { min=0;//同時分鐘數清零 hour++; //boom=1; //delay(5); //boom=0; if(hour==24)//小時加到24則小時清零 { hour=0; day++; week++; if(week>7) { week=1; } if(mon==1) { if(day>31) { day=1; mon++; } } if(mon==2) { if((year%4==0 &&year%100!=0)||year%4==0) { if(day>29) { day=1; mon++; } } else if(day>28) { day=1; mon++; } } if(mon==3) { if(day>31) { day=1; mon++; } } if(mon==4) { if(day>30) { day=1; mon++; } } if(mon==5) { if(day>31) { day=1; mon++; } } if(mon==6) { if(day>30) { day=1; mon++; } } if(mon==7) { if(day>31) { day=1; mon++; } } if(mon==8) { if(day>31) { day=1; mon++; } }if(mon==9) { if(day>30) { day=1; mon++; } } if(mon==10) { if(day>31) { day=1; mon++; } } if(mon==11) { if(day>30) { day=1; mon++; } } if(mon==12) { if(day>31) { day=1; mon=1; ye2++; } } } write_sfm(0x4e,week); write_sfm(0x48,day); write_sfm(0x45,mon); write_sfm(0x40,ye1); write_sfm(0x42,ye2); } write_sfm(0,hour);//小時若變化則重新寫入 } write_sfm(3,min);//分鐘若變化則重新寫入 } write_sfm(6,sec);//秒若變化則重新寫入 if((hour==shi&& min==fen) && sec==miao) { boom=1; delay(5); boom=0; } }
|