時間片輪詢法(數(shù)碼管顯示——中斷消抖)
本文章是關于運用時間片輪詢法(前后臺系統(tǒng)),完成對時鐘的簡單控制,同時通過中斷完成對按鍵的消失抖,顯示程序中靜態(tài)變量變量的定義是關鍵,
對按鍵消抖應該是未按下(抬起——1)——按下(0)——抬起(1),之間需要20ms左右的延時消抖。假如按鍵按下(k1 = 0),同時由于(keydelay<<1)|k1,16ms之后keydelay = 0x00;如果按鍵未按下(k1 = 1),(keydelay<<1)|k1,16ms之后keydelay = oxff,及k1一直都未按下。
電路原理圖如下:
捕獲2.PNG (58.98 KB, 下載次數(shù): 49)
下載附件
2019-12-3 13:22 上傳
主函數(shù)
- #include "reg52.h"
- //#include "Delay.h"
- #include "Display.h"
- #include "Timer.h"
- void main()
- {
- Timer0Init(); //中斷初始化
- while(1)
- {
- Datapros();
- TaskProcess();
- KeyProcess();
- }
-
- }
- Displsy.c模塊函數(shù)
- #include "Display.h"
- //#include "Delay.h"
- #include "Timer.h"
- unsigned char Bit_Selection[8]={0xfe,0Xfd,0Xfb,0Xf7,0Xef,0Xdf,0Xbf,0x7f}; //位選
- unsigned char smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//段選0123456789
- unsigned char hour = 20,min = 51,sec = 58; //定義變量
- unsigned char DisplayData[8];
- bit keyback = 1;//按鍵之前的狀態(tài)
- bit keystay = 1; //按鍵現(xiàn)在的狀態(tài)
- void DigDisplay()
- {
- static unsigned char i; //定義靜態(tài)變量
-
- P0 = 0x00; //消影
- P2 = Bit_Selection[i]; //位選
- P0 = DisplayData[i]; //段選
-
- i++;
- if(i==8)
- {
- i = 0;
- }
- }
- void Datapros()
- {
- DisplayData[0]=smgduan[hour/10];
- DisplayData[1]=smgduan[hour%10];
- DisplayData[2]=0x40;
- DisplayData[3]=smgduan[min/10];
- DisplayData[4]=smgduan[min%10];
- DisplayData[5]=0x40;
- DisplayData[6]=smgduan[sec/10];
- DisplayData[7]=smgduan[sec%10];
-
-
- }
- void Clock_Chang()//時間自加函數(shù)
- {
- sec++; //每一秒鐘執(zhí)行一次
- if(sec==60)
- {
- sec = 0;
- min++;
- if(min==60)
- {
- min = 0;
- hour++;
- if(hour==24)
- hour = 0;
- }
- }
-
- }
- void KeyProcess()
- {
- static unsigned char keymin;
- keymin=min;
- if(keystay!=keyback)//判斷按鍵現(xiàn)在狀態(tài)與之前狀態(tài)是否有變化
- {
- if(keyback==0) //如果之前狀態(tài)是零,則說明按鍵有觸發(fā)
- {
- keymin++;
- if(keymin==60)
- keymin=0;
- }
- }
- min=keymin;
- keyback = keystay; //按鍵狀態(tài)賦值
- }
- void Keyscan()//按鍵掃描,在中斷中處理
- {
- static unsigned char keydelay=0xff;
- keydelay=(keydelay<<1)|k1; //通過Keydelay移位延時,每2ms移動一位
- //keydelay=(keydelay<<1)|k2;
- //keydelay=(keydelay<<1)|k3;
- if(keydelay==0x00) //如果16ms后keydelay=0x00,則按鍵狀態(tài)置為0(按下)
- {
- keystay = 0;
- }
- if(keydelay==0xff)
- {
- keystay = 1;
- }
-
- }
- void ClockProcess()//鬧鐘判斷函數(shù)
- {
- unsigned char nhour = 20,nmin = 52,nsec = 1; //定義變量
- if((nsec==sec)&&(nmin==min)&&(nhour==hour))
- {
- beep=~beep;
- D1 = 0;
- }
- if(sec==nsec+2)//兩秒鐘之后在發(fā)生變化
- {
- beep=~beep;
- D1 = 1;
- }
-
- }
- Timer.c模塊函數(shù)
- #include "Timer.h"
- #include "Display.h"
- //#include "Delay.h"
- typedef struct SUSPEND_VARIABLE
- {
- unsigned char Flag; // 程序運行標記:0-不運行,1運行
- unsigned long Time; // 計時器
-
- unsigned long ItvTime; // 任務運行間隔時間
-
- void (*Function)(void); // 要運行的任務函
-
- }VARIABLE;
- VARIABLE TaskCount[] =
- {
- {0,5,5,DigDisplay},//顯示
- {0,1000,1000,Clock_Chang},//時鐘秒自加
- {0,1000,1000,ClockProcess},//鬧鐘
- {0,2,2,Keyscan},//按鍵掃描
- };//聲明
- void Timer0Init()
- {
- TMOD = 0X01; //選擇為定時器0模式,工作方式1,僅用TR0打開啟動。
- TH0 = 0Xfc; //給定時器賦初值,定時100us
- TL0 = 0X18; //給定時器賦初值如何是FF,定時1us
- ET0 = 1; //打開定時器0中斷允許
- EA = 1; //打開總中斷
- TR0 = 1; //打開定時器
- }
- void Timer0() interrupt 1
- {
- unsigned char i;[align=left][color=#007000][backcolor=transparent][font=Tahoma,&][size=14px] [/size][/font][/backcolor][/color][/align][align=left][color=#007000][backcolor=transparent][font=Tahoma,&][size=14px]//#define COUNT 4 //中斷函數(shù)運行函數(shù)數(shù)量 [/size][/font][/backcolor][/color][/align]
- TH0 = 0Xfc; //給定時器賦初值,定時100us
- TL0 = 0x18;
- for(i = 0;i<COUNT;i++) //循環(huán)掃描,判斷哪一個任務定時時間已到
- {
- if(TaskCount[i].Time)
- {
- TaskCount[i].Time--; //如果定時時間已到則清零,標記置一
- if(TaskCount[i].Time==0)
- {
- TaskCount[i].Flag = 1;
- TaskCount[i].Time = TaskCount[i].ItvTime; // 恢復計時器值,從新下一次
- }
- }
- }
- }
- void TaskProcess() //處理函數(shù)
- {
- unsigned char i;
- for (i=0; i<COUNT; i++) // 循環(huán)判斷那一個任務需要運行,逐個任務時間處理
- {
- if (TaskCount[i].Flag) // 時間不為0
- {
- TaskCount[i].Function(); // 運行任務
- TaskCount[i].Flag = 0; // 標志清0
- }
- }
- }
復制代碼
|