這次我們用4個獨立按鍵和8位數碼管來做一個正計數器和倒計時器,到時間后(正計時最大值,倒計時最小值)LED燈閃爍10秒熄滅(大家可以先自己想好步驟,再看一下我下面的思路步驟)我用的單片機是STC89C52
主要的步驟:1、先思考正計數,倒計數需要定時器中斷。還需要按鍵處理函數。另外需要一個數碼管顯示函數。
2、如何將這三個程序有序的排列組合起來形成一個完整的程序,這時我們可以從正計時器入手(也可以從倒計時入手)(由簡入深,抓住主干)先規定K1代表正計數器的開和關,K2代表秒分時的移位,K3代表自加,K4代表自減。還有就是正計數到達最大值的時候LED燈進行閃爍。
3、這時就要用標志位來分清關系。
第一部分按鍵程序,具體操作就是用flag0代表正計數器的開關,knum代表K2按下的時候到底是秒分時哪個 ,K3代表按一下加,K4代表按一下減,這時我們的按鍵程序基本完成;
第二部分就是我們的定時器中斷函數,因為定時器我選的時16位非自動重裝10ms,所以要累計100次到一秒,大家要注意如果你選的是1ms定時,就需要累計1000次,記著你的數據類型要選int或者unsigned int,這部分容易忽略。還有當K2按下,標志位knum進行改變也就代表著秒分時要開始閃爍。這時要進行計數操作也就是當計數時間到時,flag1進行改變,控制秒分時的閃爍時間間隔。當計數時間到的時候還需要flag2的改變這樣控制LED燈的閃爍頻率以及時間。
第三部分就是我們的數碼管顯示程序,這個程序要根據knum的值進行改變,當knum=0時它直接進行顯示,當knum!=0也就是K2按下的時候,根據flag1的值來閃爍。
第四部分就是我們要看到效果,當正計數器到達最大值的時候LED燈開始閃爍。只需在正計數結束的時候控制flag2。
第五部分當你把前四部分都解決了之后,那么你就可以著手做互鎖關系了,當我們正計數的時候我們不能進行移位操作,也就是說正計數器的開啟與移位操作形成互鎖(我們可以加if語句這樣就實現了)。
接下來就是K3,4長按和短按操作,短按加減一次,長按連加減。
我們想要實現的還有倒計時器的設定這時我們可以將K1也設定為長按和短按,長按倒計時器,短按正計數器。同時此時也會出現兩者的相互干擾情況,于是再設定一個互鎖,這樣就就避免了(用if語句來解決,就用我們現成的標志位)。因為我們將K1,K3,K4都用了長按短按,所以就讓K2的長按也有功能,就是全體清零,LED燈閃爍。
第六部分就是大家發現了嗎?就是在進行長按的時候,由于我們這時候還想要數碼管繼續顯示,所以我在長按的while循環里做了顯示,但這個顯示函數單次顯示只用了1ms,這樣我們顯示了八次,再加上一次延時1ms,我近似認為一次長按循環所需時間為10ms,這一點大家做長按,短按的時候會遇到的,還有就是數碼管顯示函數的延時時間長短,會改變數碼管亮度。大家可以自己寫一下這個程序,寫完就理解我為什么要這樣寫了。
有錯誤請指出,謝謝。
單片機源程序如下:
- #include"digdisplay.h"
- sbit k1=P3^1; //短按進行計數操作,長按進行倒計時操作
- sbit k2=P3^0; //短按進行秒分時的移位閃爍,長按進行秒分時歸零,沒有移位閃爍,LED燈閃爍開始
- sbit k3=P3^2; //短按進行秒分時(看K2讓誰閃爍)的加一操作 ,長按進行連加操作(K2讓誰閃爍)
- sbit k4=P3^3; //短按進行秒分時(看K2讓誰閃爍)的減一操作 ,長按進行連減操作(K2讓誰閃爍)
- sbit led=P2^0; //當計數到最大值時LED燈開始閃爍,當倒計時到零時開始閃爍
- u8 datenume[6]={0,0,0,0,0,0}; //當做存儲秒分時的值,通過運算轉換為數碼管顯示的值
- u8 miao=0,fen=0,shi=0,count,knum=0,flag0=0,time=0,flag1=0,flag2=0,flag3=0,time_count=0; //flag0是否進行計數操作,falg1秒分時的閃爍標志位,falg2是定時或計數到時LED燈進行閃爍,flag3是否進行倒計時操作,knum進行移位操作的標志性
- u8 a,b,c,d,e; //這幾個都代表數值,計算時間用的,你可以在程序中發現它們
- void Delay5ms() //@12.000MHz
- {
- unsigned char i, j;
- i = 10;
- j = 183;
- do
- {
- while (--j);
- } while (--i);
- }
- void keyprogress() //對四個固定按鍵進行操作,具體操作如下
- {
- if(!k1)
- {
- Delay5ms();
- if(!k1)
- {
- while(!k1)
- {
- digdisplay(0,datenume[0]);
- digdisplay(1,datenume[1]);
- digdisplay(2,16);
- digdisplay(3,datenume[2]);
- digdisplay(4,datenume[3]);
- digdisplay(5,16);
- digdisplay(6,datenume[4]);
- digdisplay(7,datenume[5]);
- d++;
- Delay1ms();
- if(d==100)
- {
- if(knum==0&&flag0==0&&(miao!=0||fen!=0||shi!=0)) //計數器和倒計時形成互鎖當秒分時都為零時不能進行倒計時
- {
- flag3=!flag3; //開啟倒計時和關閉倒計時
- }
- }
- }
- if(d<100)
- {
- if(knum==0&&flag3==0) //當沒進行移位操作時才可以啟動計數器,解決了移位時計數器開啟問題,互鎖
- { //計數器和倒計時形成互鎖
- flag0=!flag0; //開啟計數器和關閉計數器
- }
- }
- d=0;
- }
- }
- if(!k2)
- {
- Delay5ms();
- if(!k2)
- {
- while(!k2)
- {
- digdisplay(0,datenume[0]);
- digdisplay(1,datenume[1]);
- digdisplay(2,16);
- digdisplay(3,datenume[2]);
- digdisplay(4,datenume[3]);
- digdisplay(5,16);
- digdisplay(6,datenume[4]);
- digdisplay(7,datenume[5]);
- e++;
- Delay1ms();
- if(e==100) //全體歸零LED燈閃爍
- {
- flag0=0;
- flag1=0;
- flag2=1;
- flag3=0;
- knum=0;
- shi=0;
- fen=0;
- miao=0;
- }
- }
- if(flag0==0&&e<100) //解決了當移位操作時計數器開啟問題,形成必須要計數器關閉才能開始移位,形成互鎖
- {
- knum++;
- if(knum==4)
- {
- knum=0;
- }
- }
- e=0;
- }
- }
- if(!k3) //必須在有移位操作的時候才能加,也算一個鎖定
- {
- Delay5ms();
- if(!k3)
- {
- while(!k3)
- {
- digdisplay(0,datenume[0]);
- digdisplay(1,datenume[1]);
- digdisplay(2,16);
- digdisplay(3,datenume[2]);
- digdisplay(4,datenume[3]);
- digdisplay(5,16);
- digdisplay(6,datenume[4]);
- digdisplay(7,datenume[5]);
- Delay1ms();
- a++;
- if(a==100)
- {
- a=50;
- if(knum==1)
- {
- miao++;
- if(miao==60)
- {
- miao=0;
- }
- }
- else if(knum==2)
- {
- fen++;
- if(fen==60)
- {
- fen=0;
- }
- }
- else if(knum==3)
- {
- shi++;
- if(shi==24)
- {
- shi=0;
- }
- }
- }
- }
- if(knum!=0)
- {
- if(a<50)
- {
- if(knum==1)
- {
- miao++;
- if(miao==60)
- {
- miao=0;
- }
- }
- else if(knum==2)
- {
- fen++;
- if(fen==60)
- {
- fen=0;
- }
- }
- else if(knum==3)
- {
- shi++;
- if(shi==24)
- {
- shi=0;
- }
- }
- }
- }
- a=0;
- }
- }
- if(!k4) //必須在有移位操作時才可以自減
- {
- Delay5ms();
- if(!k4)
- {
- while(!k4)
- {
- digdisplay(0,datenume[0]);
- digdisplay(1,datenume[1]);
- digdisplay(2,16);
- digdisplay(3,datenume[2]);
- digdisplay(4,datenume[3]);
- digdisplay(5,16);
- digdisplay(6,datenume[4]);
- digdisplay(7,datenume[5]);
- Delay1ms();
- a++;
- if(a==100)
- {
- a=50;
- if(knum==1)
- {
- miao--;
- if(miao==255)
- {
- miao=59;
- }
- }
- if(knum==2)
- {
- fen--;
- if(fen==255)
- {
- fen=59;
- }
- }
- if(knum==3)
- {
- shi--;
- if(shi==255)
- {
- shi=23;
- }
- }
- }
- }
- if(a<50)
- {
- if(knum==1)
- {
- miao--;
- if(miao==255)
- {
- miao=59;
- }
- }
- else if(knum==2)
- {
- fen--;
- if(fen==255)
- {
- fen=59;
- }
- }
- else if(knum==3)
- {
- shi--;
- if(shi==255)
- {
- shi=23;
- }
- }
- }
- a=0;
- }
- }
- }
- void shuma() //做數碼管顯示函數,當knum=0時普通顯示,當knum!=0時靠標志位flag1決定閃爍
- {
- if(knum==0)
- {
- digdisplay(0,datenume[0]);
- digdisplay(1,datenume[1]);
- digdisplay(2,16);
- digdisplay(3,datenume[2]);
- digdisplay(4,datenume[3]);
- digdisplay(5,16);
- digdisplay(6,datenume[4]);
- digdisplay(7,datenume[5]);
- }
- else if(knum==1)
- {
- if(flag1)
- {
- digdisplay(0,datenume[0]);
- digdisplay(1,datenume[1]);
- digdisplay(2,16);
- digdisplay(3,datenume[2]);
- digdisplay(4,datenume[3]);
- digdisplay(5,16);
- digdisplay(6,datenume[4]);
- digdisplay(7,datenume[5]);
- }
- else
- {
- digdisplay(0,17);
- digdisplay(1,17);
- digdisplay(2,16);
- digdisplay(3,datenume[2]);
- digdisplay(4,datenume[3]);
- digdisplay(5,16);
- digdisplay(6,datenume[4]);
- digdisplay(7,datenume[5]);
- }
- }
- else if(knum==2)
- {
- if(flag1)
- {
- digdisplay(0,datenume[0]);
- digdisplay(1,datenume[1]);
- digdisplay(2,16);
- digdisplay(3,datenume[2]);
- digdisplay(4,datenume[3]);
- digdisplay(5,16);
- digdisplay(6,datenume[4]);
- digdisplay(7,datenume[5]);
- }
- else
- {
- digdisplay(0,datenume[0]);
- digdisplay(1,datenume[1]);
- digdisplay(2,16);
- digdisplay(3,17);
- digdisplay(4,17);
- digdisplay(5,16);
- digdisplay(6,datenume[4]);
- digdisplay(7,datenume[5]);
- }
- }
- else if(knum==3)
- {
- if(flag1)
- {
- digdisplay(0,datenume[0]);
- digdisplay(1,datenume[1]);
- digdisplay(2,16);
- digdisplay(3,datenume[2]);
- digdisplay(4,datenume[3]);
- digdisplay(5,16);
- digdisplay(6,datenume[4]);
- digdisplay(7,datenume[5]);
- }
- else
- {
- digdisplay(0,datenume[0]);
- digdisplay(1,datenume[1]);
- digdisplay(2,16);
- digdisplay(3,datenume[2]);
- digdisplay(4,datenume[3]);
- digdisplay(5,16);
- digdisplay(6,17);
- digdisplay(7,17);
- }
- }
- }
- void main()
- {
- TMOD &= 0xF0; //設置定時器模式
- TMOD |= 0x01; //設置定時器模式
- TL0 = 0xF0; //設置定時初值 10毫秒定時器
- TH0 = 0xD8; //設置定時初值
- TF0 = 0; //清除TF0標志
- TR0=1; //定時器開啟 定時器在程序運行過程中將一直啟動
- ET0=1;
- EA=1;
- while(1)
- {
- keyprogress(); //按鍵處理函數分別處理K1,K2,K3,K4的長按和短按程序
- shuma(); //數碼管管顯示程序,處理K2按鍵按下
- }
- }
- void int0() interrupt 1
- {
- TL0 = 0xF0; //設置定時初值
- TH0 = 0xD8; //設置定時初值
- datenume[0]=miao%10; //對秒分時進行數據處理,用數碼管顯示做鋪墊
- datenume[1]=miao/10;
- datenume[2]=fen%10;
- datenume[3]=fen/10;
- datenume[4]=shi%10;
- datenume[5]=shi/10;
- if(flag0&&knum==0) //進行正向計數,knum判斷是否進行了移位操作,flag0判斷是否進行了開始操作
- {
- count++;
- if(count==100)
- {
- count=0;
- miao++;
- if(miao==60)
- {
- miao=0;
- fen++;
- if(fen==60)
- {
- fen=0;
- shi++;
- if(shi==24)
- {
- shi=0;
- flag2=!flag2; //開啟LED燈的閃爍
- flag0=!flag0; //關閉計數器
- }
- }
- }
- }
- }
- if(flag3&&knum==0) //進行倒計時操作
- {
- time_count++;
- if(time_count==100)
- {
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
51hei.png (17.3 KB, 下載次數: 34)
下載附件
2020-2-15 14:13 上傳
所有資料51hei提供下載:
數碼管與按鍵的組合使用.rar
(39.3 KB, 下載次數: 26)
2020-2-11 12:59 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|