|
一、硬件電路 六位數(shù)字鐘仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
圖6-1總電路圖
2、時(shí)間調(diào)試 記時(shí)時(shí)間,如圖6-1為“01:13:38”,圖6-2所示20秒后的時(shí)間“01:13:38”,調(diào)試顯示正常。 圖6-1 01:13:38 圖 6-2 01:13:38 調(diào)整時(shí)間,如圖6-2到圖6-4所示,為修改位閃爍狀態(tài),圖6-5和圖6-6為修改后的時(shí)間和退出修改3秒后的時(shí)間,調(diào)試顯示正常。 圖6-2修改秒個(gè)位閃爍“滅” 圖6-3修改秒個(gè)位閃爍“亮” 圖6-4修改分個(gè)位閃爍“滅” 圖6-5修改后時(shí)間 圖6-6退出修改
3、鬧鐘調(diào)試 如圖6-7所示,長(zhǎng)按key2,右下角紅色led亮,表示開啟鬧鐘,并設(shè)置鬧鐘時(shí)間為“01:14:00”。若無開啟鬧鐘如圖6-8所示,到設(shè)定時(shí)間時(shí),綠色LED無反應(yīng)。如圖6-9和圖6-10所示,開啟鬧鐘,到設(shè)定時(shí)間,綠色led亮10s后熄滅。如圖6-11所示,鬧鐘“響起”后,按下key2取消“鬧鈴”,綠色led熄滅。 圖6-7 設(shè)定鬧鐘01:14:00 圖6-8無開啟鬧鐘,到時(shí)無反應(yīng) 圖6-9到鬧鐘時(shí)間 圖6-10 鬧鐘10s后停止 圖6-11鬧鐘手動(dòng)停止
4、日期調(diào)試 如圖6-12和圖6-13所示,在顯示模式下流動(dòng)顯示8位數(shù)“2022年3月1日”。如圖6-14至圖6-16所示,當(dāng)年分為閏年“2020”時(shí),2月末為29日,過24點(diǎn),變成“2020年03月01日”。如圖6-17至圖6-19所示,當(dāng)年分為平年“2021”時(shí),2月末為28日,過24點(diǎn),變成“2021年03月01日”。
圖6-12 顯示日期2022年03月 圖6-13 顯示日期2022年03月01日 圖6-17 平年2月28日 圖6-18 設(shè)定當(dāng)天23:59:49 圖6-19 24點(diǎn)后日
單片機(jī)源程序如下:
- #include<reg51.h> //包含51單片機(jī)頭文件
- #include<intrins.h> //包含標(biāo)準(zhǔn)函數(shù)庫
- sbit P_alarm =P1^6; //鬧鐘開啟與關(guān)閉指示燈,低電平有效,滅代表鬧鐘關(guān)閉
- sbit P_alarming=P1^7; //鬧鈴指示燈,到時(shí)則亮,低電平有效
- unsigned char code dis_7[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
- //七段共陰顯示數(shù)碼管“0~9”陰碼
- unsigned char data time[3]={23,59,58};
- //時(shí)間,從左到右分別為“小時(shí)、分鐘、秒”
- unsigned char data clock[3]={23,0,0};
- //鬧鐘,從左到右分別為“小時(shí)、分鐘、秒”
- unsigned char data date[4]={20,18,02,20};
- //日期, 從左到右分別為“年前兩位、年后兩位、月、日”
- unsigned char data day[12]={31,28,31,30,31,30,31,30,31,30,31,30};
- //12個(gè)月對(duì)應(yīng)的天數(shù)
- unsigned char data *p; //指針變量,指向當(dāng)前顯示地址
- unsigned char data mcs,ms_10; //計(jì)數(shù)器,mcs每250us加1次記錄40次,ms_10記錄mcs 100次
- unsigned char data position=1; //編輯模式下,記錄當(dāng)前修改位“1~6”分別表示數(shù)碼管右到左標(biāo)號(hào)
- unsigned char data screen=1; //顯示模式下,記錄當(dāng)前顯示屏幕功能,如下:“1”代表time,“2”代表clock,“3”代表date
- unsigned int data fliker; //編輯模式下,修改位閃爍功能定時(shí)計(jì)數(shù)器
- unsigned int data flow; //顯示模式下,日期流動(dòng)計(jì)數(shù)器
-
- bit edit; //“0”代表顯示模式,“1”代表編輯模式
- bit day_flag=0; //24點(diǎn)標(biāo)志位
- bit disp_num; //顯示數(shù)據(jù)位數(shù)切換,“0”代表顯示6位,即時(shí)間,“1”代表顯示日期
- bit alarm,alarming; //鬧鐘狀態(tài)和鬧鈴狀態(tài)標(biāo)志位
-
-
- void display(unsigned char *p); //顯示函數(shù)
- void clock_c(); //鬧鐘功能程序
- void date_c(); //日期程序
- unsigned char keyscan(); //鍵盤掃描程序,另外,K1長(zhǎng)按進(jìn)行模式切換
- void key2_function_d(); //顯示狀態(tài),按鍵2功能程序,鬧鐘取消\啟動(dòng),鬧鈴消停
- void key2_function_e(); //編輯狀態(tài),按鍵2功能程序,加1
- void key1_function_d(); //顯示狀態(tài),按鍵2功能程序,顯示切換
- void key1_function_e(); //編輯狀態(tài),按鍵2功能程序,修改位切換
- void delay(unsigned int i); //延時(shí)函數(shù)
-
-
-
- void main()
- {
- unsigned char keyboard,key;
- TMOD=0x02; //設(shè)置定時(shí)器0工作方式為2
- TL0=0x06; //設(shè)置低八位初始值
- TH0=0x06; //設(shè)置高八位初始值
- EA=1; //開啟總中斷
- ET0=1; //開啟定時(shí)器0中斷允許
- TR0=1; //啟動(dòng)定時(shí)起0
- p=time; //指向時(shí)間地址
- while(1)
- {
- keyboard=P1&0x03; //讀取按鍵的值,并且屏蔽無關(guān)位
- display(p); //調(diào)用顯示函數(shù)
- clock_c(); //調(diào)用鬧鐘函數(shù)
- date_c(); //調(diào)用日期函數(shù)
- if((screen==1)&&(edit==1))TR0=0;else TR0=1;
- //修改時(shí)間時(shí),關(guān)閉定時(shí)器
- if(keyboard!=0x03) //若有按鍵按下,則執(zhí)行以下程序
- {
- display(p); //顯示函數(shù)消除按鍵抖動(dòng)
- if(keyboard!=0x03) //再次檢測(cè),若有,則執(zhí)行以下程序
- {
- key=keyscan(); //調(diào)用按鍵掃描程序,讀取按鍵值
- if(!edit) //顯示模式
- {
- switch(key) //如果KEY1按下,則KEY1為1,若KEY2按下則為2
- {
- case 1:key1_function_d();break;//顯示屏幕切換
- case 2:key2_function_d();break;//鬧鐘功能設(shè)置,鬧鈴取消
- default:break;
- }
- }
- else //編輯模式
- {
- switch(key) //如果KEY1按下,則KEY1為1,若KEY2按下則為2
- {
- case 1:key1_function_e();break;//修改位切換
- case 2:key2_function_e();break;//加1
- default:break;
- }
- } } } } }
- void display(unsigned char *p) //顯示子程序,顯示參數(shù)為無符號(hào)字符型指針變量
- {
- unsigned char disp[8]={0,0,0,0,0,0,0,0};
- //顯示數(shù)據(jù)緩存變量
- unsigned char disp_com[6]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
- //數(shù)碼管位控端分別代表從左到右“1~6”號(hào)數(shù)碼管
- unsigned char a,b,d,dot;
- unsigned char c=0;
- if(!disp_num)a=6;else a=8; //顯示時(shí)間則a=6,否則a=8
- for(b=0;b<a;b++) //將顯示數(shù)據(jù)按位緩存與disp數(shù)據(jù)中
- {
- if(c==0)disp[b]=p[b/2]/10;
- else disp[b]=p[b/2]%10;
- c++;if(c==2)c=0;
- }
- if(!edit) //顯示模式
- {
- if(!disp_num) //顯示時(shí)間
- {
- for(b=0;b<6;b++)
- {
- if(b==1||b==3)dot=128;else dot=0;
- //1為小時(shí)個(gè)位,3為分鐘個(gè)位,其后面加小數(shù)點(diǎn)
- P0=0xff; //消影
- P2=~dis_7[disp[b]]+dot;//段碼刷新
- P0=disp_com[b]; //位選端有效,顯示輸出
- delay(5); //延時(shí)
- }
- }
- else //顯示日期
- {
- b=flow/50; //flow最大為400,每顯示50次流動(dòng)一位
- for(c=0;c<6;c++)
- {
- d=c+b;if(d>7)d-=8; //每次顯示6位,但流動(dòng)顯示起始位,第9位時(shí)返回第1位顯示
- if(d==3||d==5||d==7)dot=128;else dot=0;
- //年份、月份、日期個(gè)位加小數(shù)點(diǎn)
- P0=0xff; //消影
- P2=~dis_7[disp[d]]+dot;//斷碼刷新
- P0=disp_com[c]; //輸出位選端
- delay(5); //延時(shí)
- }
- flow++; //每顯示1次屏幕加1;
- if(flow==400)flow=0; //最大399
- }
- }
- else //編輯模式
- {
- fliker++;if(fliker>100)fliker=0;//修改位顯示閃爍功能
- if(!disp_num) //顯示時(shí)間
- {
- for(b=0;b<6;b++)
- {
- if(b==1||b==3)dot=128;else dot=0;
- P0=0xff;
- P2=~dis_7[disp[b]]+dot;
- if(b==(6-position)) //修改位閃爍,position=1代表修改第6位數(shù)碼管,最右邊數(shù)碼管
- {
- if(fliker<50)P0=disp_com[b]; //亮
- else P0=0xff; //滅
- }
- else P0=disp_com[b];
- delay(5);
- }
- }
- else //顯示日期
- {
- if(position>6)b=0;else b=2; //顯示日期移動(dòng),起始顯示狀態(tài)“年,月”
- for(c=0;c<6;c++)
- {
- d=c+b; //起始位置為disp[0或者2]
- if(d==3||d==5)dot=128;else dot=0;
- P0=0xff;
- P2=~dis_7[disp[d]]+dot;
- if(c==(6-position)||(c==(8-position)&&(position>6)))
- //修改位閃爍,年最大位開始修改(顯示“年、月”||顯示“年、月、日”)
- {
- if(fliker<50)P0=disp_com[c];
- else P0=0xff;
- }
- else P0=disp_com[c];
- delay(5);
- } } } }
- void clock_c() //鬧鐘子程序
- {
- if(alarm) //開啟鬧鐘則允許以下程序
- {
- int a,b,c;
- a=time[0]-clock[0];
- b=time[1]-clock[1];
- c=time[2]-clock[2]; //比較鬧鐘時(shí)間和當(dāng)前時(shí)間
- if((a==0)&&(b==0)&&(c==0)) //時(shí)間到
- alarming=1; //啟動(dòng)鬧鈴
- if(alarming) //鬧鈴10秒自動(dòng)取消
- {
- if((b*60+c)>=10)alarming=0;
- }
- }
- P_alarm=!alarm; //鬧鐘狀態(tài)輸出
- P_alarming=!alarming; //鬧鈴狀態(tài)輸出
- }
-
- void date_c() //日期子程序
- {
- unsigned char a,b,c,d;
- d=date[0]*100+date[1];
- a=23-time[0];
- b=59-time[1];
- c=59-time[2]; //是否到24點(diǎn)
-
- if((d%400==0)||((d%100!=0)&&(d%4==0))) //閏年
- { day[1]=29;}
- else
- { day[1]=28;if(date[3]>28)date[3]=28;} //平年
-
- if((a==23)&&(b==59)&&(c==59)&&(day_flag==0)) //日期記時(shí),24整點(diǎn)運(yùn)行1次
- {
- date[3]++; //日加1
- if(date[3]>day[date[2]-1]) //月末
- {
- date[3]=1; //日歸1
- date[2]++; //月份加1
- if(date[2]>12) //年末
- {
- date[2]=1; //月歸1
- date[1]++; //年后兩位加1
- if(date[1]>99) //99年進(jìn)位
- {
- date[0]++; //年前兩位加1
- date[1]=0; //年后兩位歸零
- if(date[0]>99) //最大9999年
- date[0]=0;
- }
- }
- }
- day_flag=1; //執(zhí)行1次標(biāo)志位置1,防止重復(fù)執(zhí)行
- }
- if(day_flag){if(c!=59)day_flag=0;} //24整點(diǎn)過后,整點(diǎn)標(biāo)志位復(fù)位
- }
-
- unsigned char keyscan() //鍵盤掃描子程序,無符號(hào)字符型子程序,返回鍵號(hào)
- {
- unsigned int a;
- unsigned char temp;
- temp=P1&0x03; //讀取按鍵輸入,屏蔽無關(guān)位
- for(a=0;a<100&&((P1&(0x07))==0x06);a++)
- //按鍵延時(shí)功能
- {
- display(p); //調(diào)用顯示程序
- if(a==99) //延時(shí)閾值
- {
- edit=!edit;
- if(screen==3)position=8;//進(jìn)入編輯模式初始狀態(tài)設(shè)置
- else position=1;a=3;temp=0;P0=0xff;delay(1000);
- //進(jìn)入編輯模式,則返回值為3不調(diào)用任何按鍵程序
- while((P1&(0x07))==0x06)display(p);
- //按鍵松開
- }
- }
- switch(temp) //根據(jù)按鍵狀態(tài)返回鍵號(hào)
- {
- case 0x06:a=1;break;
- case 0x05:a=2;break;
- default:break;
- }
- if(edit)while((P1&0x07)!=0x07)display(p);//按鍵松開
- return(a); //返回鍵號(hào)
- }
-
- void key2_function_d() //按鍵2,顯示狀態(tài),鬧鐘啟動(dòng)/停止,鬧鈴消停
- {
- unsigned int a;
- if(!edit) //顯示模式,執(zhí)行以下程序
- {
- for(a=0;(a<100)&&((P1&(0x07))==0x05);a++)
- //按鍵延時(shí)功能
- {
- display(p); //調(diào)用顯示程序
- if(a==99) //到達(dá)延時(shí)閾值,執(zhí)行以下程序
- {
- alarm=!alarm; //開啟或取消鬧鐘
- P_alarm=!alarm; //立即輸出反饋鬧鐘狀態(tài)
- while((P1&(0x07))==0x05)display(p);//按鍵松開
- }
- }
- if(alarm) //鬧鐘開啟
- {
- if(alarming)alarming=0; //手動(dòng)取消,顯示模式下短按取消鬧鈴
- }else alarming=alarm; //鬧鐘關(guān)閉狀態(tài) }
- }
-
- void key2_function_e() //編輯模式,按鍵2,加1功能
- {
- if(edit)
- {
- if(!disp_num) //顯示時(shí)間,則執(zhí)行以下程序
- {
- switch(position) //根據(jù)位置進(jìn)行加1
- {
- case 1:if(p[2]%10<9)p[2]++;else p[2]-=9 ;break; //秒個(gè)位
- case 2:if(p[2]<50)p[2]+=10;else p[2]-=50;break; //秒十位
- case 3:if(p[1]%10<9)p[1]++;else p[1]-=9 ;break; //分鐘個(gè)位
- case 4:if(p[1]<50)p[1]+=10;else p[1]-=50;break; //分鐘十位
- case 5:if((p[0]%10)<9&&(p[0]<23))p[0]++;else{if(p[0]<20)p[0]-=9;else p[0]-=3;};break; //小時(shí)個(gè)位
- case 6:if((p[0]/10)<2&&(p[0]<14))p[0]+=10;else{if(p[0]<20)p[0]-=10;else p[0]-=20;};break; //小時(shí)十位
- default: break;
- }
- }
- else //顯示日期,則執(zhí)行以下程序
- {
-
- switch(position) //根據(jù)位置進(jìn)行加
- {
- case 8:if(p[0]<99) p[0]+=10;else p[0]%=10;break; //年千位
- case 7:if(p[0]%10<9)p[0]++; else p[0]-=9;break; //年百位
- case 6:if(p[1]<99) p[1]+=10;else p[1]%=10;break; //年十位
- case 5:if(p[1]%10<9)p[1]++; else p[1]-=9;break; //年個(gè)位
- case 4:p[3]=1;if(p[2]==1)p[2]=10;else p[2]=1;break; //若進(jìn)行月份的調(diào)整,需要重新設(shè)置日期,調(diào)整月份十位代表10以上和10以下切換
- case 3:p[3]=1;if(p[2]>=10){if(p[2]<12) p[2]++;else p[2]=10; } else if(p[2]<9) p[2]++;else p[2]=1;break; //調(diào)整月份個(gè)位
- case 2: //日期的十位
- p[3]+=10; //日期的十位加1
- if(p[3]>day[p[2]-1]) //如果超過月末
- {
- p[3]%=10; //保留日期個(gè)位
- if(p[3]==0)p[3]=10; //十位歸零
- }break;
- case 1: //日期的個(gè)位
- if((p[3]/10)==(day[p[2]-1]/10)) //如果與月末十位相
- 等則執(zhí)行以下程序
- {
- if(p[3]==day[p[2]-1]){ p[3]=p[3]-(day[p[2]-1]%10);}
- //達(dá)到月末,減去月末個(gè)位數(shù)
- else
- p[3]++; //日期加1
- }
- else //不與月末十位相等
- {
- if(p[3]%10<9)p[3]++; //最大值為9
- else
- {
- p[3]-=9;
- if(p[3]==0)p[3]=1; //日期為0時(shí)則為1
- }
- }break;
- default: break;
- }
- }
- }
- }
-
- void key1_function_d() //按鍵1,顯示狀態(tài),顯示切換
- {
- if(!edit) //顯示狀態(tài)下
- {
- screen++; //每調(diào)用1次,加1,范圍“1~3”
- switch(screen)
- {
- case 1:p=time;disp_num=0;break; //顯示時(shí)間
- case 2:p=clock;disp_num=0;break; //顯示鬧鐘
- case 3:p=date;disp_num=1;break; //顯示日期
- default:p=time;disp_num=0;screen=1;break; //顯示時(shí)間
- }
- }
- }
-
- void key1_function_e() //按鍵1,編輯模式下,移位
- {
- if(edit) //編輯模式下執(zhí)行以下程序
- {
- if(!disp_num) //顯示時(shí)間狀態(tài)
- {
- position++;
- if(position>6)position=1; //position范圍“1~6”
- }else //顯示日期
- {
- position--; //從年千位開始修改
- if(position==0||position>8)
- position=8; //范圍“1~8”
- }
- }else position=1; //復(fù)位
- }
- void delay(unsigned int i) //延時(shí)程序
- {
- unsigned int k;
- for(;i>0;i--)
- for(k=0;k<54;k++);
- }
- void time_int0() interrupt 1 //定時(shí)中斷,中斷方式2
- {
- EA=0; //關(guān)閉總中斷,防止高級(jí)中斷影響定時(shí)
- if(mcs!=0x28) //10ms定時(shí)
- mcs++;
- else
- {
- mcs=0;
- if(ms_10!=100)ms_10++ ; //1s定時(shí)
- else
- {
- ms_10=0;
- if(time[2]!=59)time[2]++; //1s到則秒位加1
- else
- {
- time[2]=0; //60秒歸0
- if(time[1]!=59)time[1]++;//分鐘加1
- else
- {
- time[1]=0; //60分鐘歸0
- if(time[0]!=23)time[0]++; //小時(shí)加1
- else time[0]=0; //24小時(shí)歸0
- }
- }
- }
- }
- EA=1; //開放總中斷
- }
復(fù)制代碼
0.png (9.17 KB, 下載次數(shù): 68)
下載附件
2018-11-15 17:12 上傳
所有資料51hei提供下載:
時(shí)鐘.zip
(4.86 MB, 下載次數(shù): 209)
2018-11-15 17:13 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|
評(píng)分
-
查看全部評(píng)分
|