|
要求:在LCD1602上實(shí)現(xiàn)年月日,時間的顯示;一個鬧鐘蜂鳴器提醒功能;一個倒計(jì)時功能
附件:keil程序+proteus 8.13 仿真
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
仿真
單片機(jī)源程序如下:- #include <reg52.h>
- #include "LCD1602.h" //LCD顯示文件
- #define uchar unsigned char
- #define uint unsigned int
- #define ulong unsigned long
- sbit BEEP=P1^0;//蜂鳴器
- sbit K1=P2^3;//設(shè)置時間按鍵
- sbit K2=P2^4;//+
- sbit K3=P2^5;//-
- sbit K4=P2^6;//設(shè)置鬧鐘按鍵
- sbit K5=P2^7;//倒計(jì)時按鍵
- int year=2025;
- char month=3,day=17,h=8,min=29,s=50;//正常走時年月日時分秒
- char nh=23,nmin=30,ns=0;//鬧鐘 時分秒
- char dmin=1,ds=0;//倒計(jì)時 分秒
- uchar run;//平年閏年標(biāo)志 0為平年,1為閏年
- uchar count,tiaoJ;//中斷計(jì)數(shù)器與調(diào)節(jié)計(jì)數(shù)器
- uchar daymax;//每月最大天數(shù)
- uchar mode;//模式
- uchar count1;//作為倒計(jì)時進(jìn)入 開始 退出標(biāo)志
- bit stop;//倒計(jì)時停止標(biāo)志位
- void delay(uint x)//延時函數(shù)
- {
- uchar i,j;
- for(i=0;i++;i<x)
- for(j=0;j++;j<256);
- }
- void travel_time()//走時函數(shù),包括平年閏年的計(jì)算
- {
- if((year/4)==0 && (year)/100!=0 || (year)/400==0 )//閏年:能被4整除且不能被100整除,或能被400整除。
- {
- run=1;
- }
- else
- {
- run=0;
- }
- switch(month)
- {
- case 1 : daymax=31; break;
- case 2 : if(run==1) {daymax=29;}else {daymax=28;} break;
- case 3 : daymax=31; break;
- case 4 : daymax=30; break;
- case 5 : daymax=31; break;
- case 6 : daymax=30; break;
- case 7 : daymax=31; break;
- case 8 : daymax=31; break;
- case 9 : daymax=30; break;
- case 10 :daymax=31; break;
- case 11 :daymax=30; break;
- case 12 :daymax=31; break;
- }
- if(s==60)//走時限制
- {
- s=0;
- min++;
- if(min==60)
- {
- h++;
- if(h==24)
- {
- h=0;
- day++;
- if(day>daymax)
- {
- day=1;
- month++;
- if(month==13)
- {
- month=1;
- year++;
- }
- }
- }
- }
- }
- //規(guī)范非零值
- if(s<0)
- {
- s=59;
- }
- if(min<0)
- {
- min=59;
- }
- if(h<0)
- {
- h=23;
- }
- if(day<0)
- {
- day=daymax;
- }
- if(month<0)
- {
- month=12;
- }
- if(year<0)
- {
- year=2025;
- }
- }
- void Countdown_time()//倒計(jì)時走時
- {
- if(ds<0)
- {
- if(dmin!=0 && ds<0)
- {
- if(stop==0)
- {
- ds=59;
- LCD_ShowChar(2,12,' ');
- dmin--;
- }
- if(dmin<0 && stop==1)
- {
- dmin=0;
- }
- }
- }
- }
- void keyscanf()
- {
- if(K1==0)
- {
- delay(5);//消抖
- if(K1==0)
- {
- switch(mode)
- {
- case 0 :{TR0=0;count=0;tiaoJ++;}break;
- default:{tiaoJ++;}break;
- }
- }
- while(K1==0);//松手檢測
- }
- if(K2==0)
- {
- delay(5);//消抖
- if(K2==0)
- {
- if(mode==0)//正常走時模式
- {
- switch(tiaoJ)
- {
- case 1 : s++;if(s>59)s=0; break;
- case 2 : min++;if(min>59)min=0;break;
- case 3 : h++; if(h>23)h=0;break;
- case 4 : day++;if(day>daymax)day=1; break;
- case 5 : month++;if(month>12)month=1;break;
- case 6 : year++; break;
- }
- }
- if(mode==1)//鬧鐘設(shè)置模式
- {
- switch(tiaoJ)
- {
- case 1 : ns++;if(ns>59)ns=0; break;
- case 2 : nmin++;if(nmin>59)nmin=0;break;
- case 3 : nh++; if(nh>23)nh=0;break;
- }
- }
- if(mode==2)//倒計(jì)時設(shè)置模式
- {
- switch(tiaoJ)
- {
- case 1 : ds++;if(ds>59)ds=0; break;
- case 2 : dmin++;if(dmin>59)dmin=0;break;
- }
- }
- }
- while(K2==0);//松手檢測
- }
- if(K3==0)
- {
- delay(5);//消抖
- if(K3==0)
- {
- if(mode==0)//正常走時模式
- {
- switch(tiaoJ)
- {
- case 1 : s--;if(s<0)s=59; break;
- case 2 : min--;if(min<0)min=59; break;
- case 3 : h--;if(h<0)h=23; break;
- case 4 : day--;if(day<0)day=daymax; break;
- case 5 : month--;if(month<0)month=12; break;
- case 6 : year--;if(year<0)year=2025; break;
- }
- }
- if(mode==1)//鬧鐘設(shè)置模式
- {
- switch(tiaoJ)
- {
- case 1 : ns--;if(ns<0)ns=59; break;
- case 2 : nmin--;if(nmin<0)nmin=59; break;
- case 3 : nh--;if(nh<0)nh=23; break;
- }
- }
- if(mode==2)//鬧鐘設(shè)置模式
- {
- switch(tiaoJ)
- {
- case 1 : ds--;if(ds<0)ds=59; break;
- case 2 : dmin--;if(dmin<0)dmin=59; break;
- }
- }
- }
- while(K3==0);//松手檢測
- }
- if(K4==0)
- {
- delay(5);//消抖
- if(K4==0)
- {
- mode=!mode;
- BEEP=1;
- tiaoJ=0;
- }
- while(K4==0);//松手檢測
- }
- if(K5==0)
- {
- delay(5);//消抖
- if(K5==0)
- {
- count1++;
- tiaoJ=0;
- count=0;
- switch(count1)
- {
- case 1 : mode=2;TR0=0;dmin=1;ds=0;break;//進(jìn)入
- case 2 : TR0=1;break; //開始
- case 3 : mode=0;count=0;stop=0;count1=0;break;//退出
- }
- }
- while(K5==0);//松手檢測
- }
- }
- void Sans_Pd()//閃爍位置判斷,與調(diào)節(jié)時間標(biāo)志清除
- {
- if(nmin==min && nh==h && mode==0)//鬧鐘判斷
- {
- BEEP=0;//蜂鳴器鳴叫,不管就是一分鐘后自動關(guān)閉,提前關(guān)閉按K4進(jìn)入設(shè)置改時間
- }
- else
- {
- BEEP=1;
- }
- if(mode==0)
- {
- switch(tiaoJ)//閃爍位置設(shè)置
- {
- case 1 : LCD_ShowString(2,10," ");delay(2000); break;
- case 2 : LCD_ShowString(2,7," ");delay(2000); break;
- case 3 : LCD_ShowString(2,4," ");delay(2000); break;
- case 4 : LCD_ShowString(1,11," ");delay(2000); break;
- case 5 : LCD_ShowString(1,8," ");delay(2000);break;
- case 6 : LCD_ShowString(1,3," ");delay(2000); break;
- }
- if(tiaoJ==7)
- {
- tiaoJ=0;
- TR0=1;//打開定時器
- }
- }
- if(mode==1)//鬧鐘設(shè)置時間時閃爍條件
- {
- switch(tiaoJ)//閃爍位置設(shè)置
- {
- case 1 : LCD_ShowString(2,10," ");delay(2000); break;
- case 2 : LCD_ShowString(2,7," ");delay(2000); break;
- case 3 : LCD_ShowString(2,4," ");delay(2000); break;
- }
- if(tiaoJ==4)
- {
- tiaoJ=1;
- }
- }
- if(mode==2)//倒計(jì)時設(shè)置時間時閃爍條件
- {
- switch(tiaoJ)//閃爍位置設(shè)置
- {
- case 1 : LCD_ShowString(2,10," ");delay(2000); break;
- case 2 : LCD_ShowString(2,7," ");delay(2000); break;
- }
- if(tiaoJ==3)
- {
- tiaoJ=1;
- }
- }
- }
- void LCD_GUI1()//萬年歷時間顯示函數(shù)
- {
- //第一行,年月日
- LCD_ShowSignedNum(1,3,year,4);
- LCD_ShowChar(1,7,'/');
- LCD_ShowSignedNum(1,8,month,2);
- LCD_ShowChar(1,10,'/');
- LCD_ShowSignedNum(1,11,day,2);
- LCD_ShowString(1,13," ");
- //第二行,時分秒
- LCD_ShowSignedNum(2,4,h,2);
- LCD_ShowChar(2,6,':');
- LCD_ShowSignedNum(2,7,min,2);
- LCD_ShowChar(2,9,':');
- LCD_ShowSignedNum(2,10,s,2);
-
- }
- void LCD_GUI2()//鬧鐘模式下的顯示函數(shù)
- {
- //第一行,年月日
- LCD_ShowString(1,3,"Alarm mode:");
- //第二行,時分秒 nh,nmin,ns;
- LCD_ShowSignedNum(2,4,nh,2);
- LCD_ShowChar(2,6,':');
- LCD_ShowSignedNum(2,7,nmin,2);
- LCD_ShowChar(2,9,':');
- LCD_ShowSignedNum(2,10,ns,2);
- }
- void LCD_GUI3()//鬧鐘模式下的顯示函數(shù)
- {
- //第一行,年月日
- LCD_ShowString(1,3,"Countdown mode:");
- //第二行,時分秒 nh,nmin,ns;
- LCD_ShowString(2,4," ");
- LCD_ShowSignedNum(2,7,dmin,2);
- LCD_ShowChar(2,9,':');
- LCD_ShowSignedNum(2,10,ds,2);
- }
- void Timer0_Init()//定時器0初始化
- {
- TMOD=0x01;
- //50ms進(jìn)中斷
- TH0=(65535-50000)/256;
- TL0=(65535-50000)%256;
- TR0=1;
- EA=1;
- ET0=1;
- }
- void main()
- {
- LCD_Init();//讓LCD1602準(zhǔn)備工作起來
- Timer0_Init();//打開中斷,使能時鐘,設(shè)置隔多久進(jìn)一次中斷 服務(wù)函數(shù)
- BEEP=1;//蜂鳴器不叫
- while(1)
- {
- keyscanf();//按鍵掃描
- Sans_Pd();//閃爍判定
- //萬年歷模式下
- switch(mode)
- {
- case 0 : {travel_time();LCD_GUI1();delay(2000);}break;
- case 1 : {LCD_GUI2();}break;
- case 2 : {Countdown_time();LCD_GUI3();}break;
- }
- }
- }
- void Timer0_Routine() interrupt 1 //定時器0,中斷服務(wù)函數(shù)
- {
- count++;
- if(count==20)//1s
- {
- count=0;
- if(mode==0)//正常走時
- s++;
- if(mode==2)//倒計(jì)時
- if(dmin!=0 || ds!=0)
- ds--;
- else
- {
- stop=1;
- }
- }
- }
復(fù)制代碼
下載:
C51_數(shù)字電子鐘.7z
(224.42 KB, 下載次數(shù): 0)
2025-4-1 20:10 上傳
點(diǎn)擊文件名下載附件
|
評分
-
查看全部評分
|