用51微控制器做一個電子鐘
阿新 • • 發佈:2019-01-02
學了一個多月51了,終於整了個電子鐘出來,個人感覺還是比較有趣的。 需要注意的是我用的是普中的板子,板子型別不同,io口的功能可能會有所差異。然後我這個k1開關和k2開關是接反了的,原本k1應該是接P3^0,k2接P3^1的,結果我一測試才知道k1接到了P3^1,k2接到P3^0了,不過這不要緊,用sbit定義位變數時注意換一下就可以了。然後大概講講功能,用8個數碼管顯示目前時間和鬧鈴時間,然後用4個獨立按鍵對目前時間和鬧鈴時間進行調整(k2是加,k3是減 ,k4是用來停止鬧鈴的),第一次按k1是對目前時間秒數調整,第2次按k1是對目前時間分鐘數調整,第三次按k1是對目前時間小時數調整,第4次按k1是對鬧鈴秒數調整,第5次按k1是對鬧鈴時間分鐘數調整,第6次按k1是對鬧鈴秒數調整,第7次按k1是調整完畢,進去非調整狀態即實時顯示目前時間(不過有點差異,時間走的快了一點)。主要用到了數碼管動態顯示,獨立按鍵,定時器中斷這些。程式碼如下:
#include<reg52.h> typedef unsigned int u16; typedef unsigned char u8; sbit led=P2^0; sbit lsa=P2^2; sbit lsb=P2^3; sbit lsc=P2^4; sbit beep=P1^5; sbit k1=P3^1; sbit k2=P3^0; sbit k3=P3^2; sbit k4=P3^3; sbit dian=P0^7; u8 keyvalue,alarmexist=0; u8 smgduan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67,0x00};//段選碼,分別對應0到無 u16 cnt=0,i=0,j=0,flag=0,time[]={0,0,0,0,0,0,0,0};//只用數碼管0,1 3,4 6,7 u16 alarm[]={0,0,0,0,0,0,1,0}; u16*p; void delay(u16 mmp); void t0andt1init(); void addproct(int x); void addproca(int x); void reduceproct(int x); void reduceproca(int x); void keyscan(); void jia(); void jian(); void main() { led=0; t0andt1init(); P0=0x00; while(1) { if(time[0]==alarm[0]&&time[1]==alarm[1]&&time[3]==alarm[3]&&time[4]==alarm[4]&&time[6]==alarm[6]&&time[7]==alarm[7])//滿足條件 蜂鳴器以一定的時間間隔響,只到K4按鍵並鬆開,此時數碼管任然正常顯示當前時間 { alarmexist=0; while(k4) { beep=~beep; delay(25); beep=~beep; delay(25); } } keyscan(); } } void delay(u16 mmp) { while(mmp--); } void t0andt1init() { TMOD=0x11; TH0=0xfc; TL0=0x67;//賦定時器初始值,定時1ms TH1=0xfc; TL1=0x67; TR0=1;//T0定時器開始定時 EA=1; ET0=1; ET1=1; } void addproct(int x) //對非調整狀態和調整狀態的加1處理(僅用於對當前時間) { if(x==0||x==3||x==6) if(time[x]==10) { time[x]=0; time[x+1]=time[x+1]+1; addproct(x+1); } if(x==1||x==4) if(time[x]==6) { time[x]=0; time[x+2]=time[x+2]+1; addproct(x+2); } if(time[6]==4&&time[7]==2) time[6]=time[7]=0; } void addproca(int x) //對調整狀態的加1處理(僅用於對鬧鐘時間) { if(x==0||x==3||x==6) if(alarm[x]==10) { alarm[x]=0; alarm[x+1]=alarm[x+1]+1; addproca(x+1); } if(x==1||x==4) if(alarm[x]==6) { alarm[x]=0; alarm[x+2]=alarm[x+2]+1; addproca(x+2); } if(alarm[6]==4&&alarm[7]==2) alarm[6]=alarm[7]=0; } void reduceproct(int x) // 對調整狀態的減1處理(僅用於對當前時間) { if(time[0]==0&&time[1]==0&&time[3]==0&&time[4]==0&&time[6]==0&&time[7]==0) { time[0]=time[3]=9; time[1]=time[4]=5; time[6]=3; time[7]=2; return ; } if(x==0||x==3||x==6) { if(time[x]>=1) time[x]=time[x]-1; else { if(time[7]==0&&x==6) { time[6]=3; time[7]=2; } else { time[x]=9; reduceproct(x+1); } } } else { if(time[x]>=1) time[x]=time[x]-1; else { time[x]=5; if(x!=7) reduceproct(x+2); else time[x]=1; } } } void reduceproca(int x) // 對調整狀態的減1處理(僅用於對鬧鐘時間) { if(alarm[0]==0&&alarm[1]==0&&alarm[3]==0&&alarm[4]==0&&alarm[6]==0&&alarm[7]==0) { alarm[0]=alarm[3]=9; alarm[1]=alarm[4]=5; alarm[6]=3; alarm[7]=2; return ; } if(x==0||x==3||x==6) { if(alarm[x]>=1) alarm[x]=alarm[x]-1; else { if(alarm[7]==0&&x==6) { alarm[6]=3; alarm[7]=2; } else { alarm[x]=9; reduceproca(x+1); } } } else { if(alarm[x]>=1) alarm[x]=alarm[x]-1; else { alarm[x]=5; if(x!=7) reduceproca(x+2); else alarm[x]=1; } } } void keyscan() { flag=0; keyvalue=0; if(k1==0) { TR0=0;//不在顯示當前時間 TR1=1; delay(1000); if(k1==0) { while(!k1) ; delay(1000); led=~led; keyvalue++; } else return ; while(keyvalue!=7) { if(k1==0) { delay(1000); if(k1==0) { while(!k1) ; led=~led; keyvalue++; if(keyvalue==4) flag=1; } } if(k2==0) { delay(1000); if(k2==0) { while(!k2) ; led=~led; jia(); } } if(k3==0) { delay(1000); if(k3==0) { while(!k3) ; led=~led; jian(); } } } TR0=1; TR1=0; if(((alarm[6]+alarm[7]*10)*60+alarm[3]+alarm[4]*10)>((time[6]+time[7]*10)*60+time[3]+time[4]*10))//判斷鬧鐘時間是否大於當前時間, alarmexist=1; else alarmexist=0; } } void jia() { switch(keyvalue) { case 1:time[0]=time[0]+1;addproct(0);break; case 2:time[3]=time[3]+1;addproct(3);break; case 3:time[6]=time[6]+1;addproct(6);break; case 4:alarm[0]=alarm[0]+1;addproca(0);break; case 5:alarm[3]=alarm[3]+1;addproca(3);break; case 6:alarm[6]=alarm[6]+1;addproca(6);break; } } void jian() { switch(keyvalue) { case 1:reduceproct(0);break; case 2:reduceproct(3);break; case 3:reduceproct(6);break; case 4:reduceproca(0);break; case 5:reduceproca(3);break; case 6:reduceproca(6);break; } } void Timer0() interrupt 1//非調整時,執行的中斷服務程式 { TH0=0xfc; TL0=0x67;//賦定時器初始值,定時1ms cnt++; if(1000==cnt) { cnt=0; time[0]=time[0]+1; addproct(0); } P0=0X00; switch(i) { case 0:lsa=0;lsb=0;lsc=0;P0=smgduan[time[0]];dian=(alarmexist==1)?1:0;i++;break; case 1:lsa=1;lsb=0;lsc=0;P0=smgduan[time[1]];i++;i++;break; case 3:lsa=1;lsb=1;lsc=0;P0=smgduan[time[3]];i++;break; case 4:lsa=0;lsb=0;lsc=1;P0=smgduan[time[4]];i++;i++;break; case 6:lsa=0;lsb=1;lsc=1;P0=smgduan[time[6]];i++;break; case 7:lsa=1;lsb=1;lsc=1;P0=smgduan[time[7]];i=0;break; } } void Timer1() interrupt 3 //調整時,執行的中斷服務程式 ,flag=0顯示正在調整的time,為1顯示正在調整的alarm { TH1=0xfc; TL1=0x67;//賦定時器初始值,定時1ms if(flag==0) p=time; else p=alarm; P0=0X00; switch(j) { case 0:lsa=0;lsb=0;lsc=0;P0=smgduan[p[0]];j++;break; case 1:lsa=1;lsb=0;lsc=0;P0=smgduan[p[1]];j++;j++;break; case 3:lsa=1;lsb=1;lsc=0;P0=smgduan[p[3]];j++;break; case 4:lsa=0;lsb=0;lsc=1;P0=smgduan[p[4]];j++;j++;break; case 6:lsa=0;lsb=1;lsc=1;P0=smgduan[p[6]];j++;break; case 7:lsa=1;lsb=1;lsc=1;P0=smgduan[p[7]];j=0;break; } }