时间片轮询法(数码管显示——中断消抖)
本文章是关于运用时间片轮询法(前后台系统),完成对时钟的简单控制,同时通过中断完成对按键的消失抖,显示程序中静态变量变量的定义是关键,
对按键消抖应该是未按下(抬起——1)——按下(0)——抬起(1),之间需要20ms左右的延时消抖。假如按键按下(k1 = 0),同时由于(keydelay<<1)|k1,16ms之后keydelay = 0x00;如果按键未按下(k1 = 1),(keydelay<<1)|k1,16ms之后keydelay = oxff,及k1一直都未按下。
电路原理图如下:
主函数
- #include "reg52.h"
- //#include "Delay.h"
- #include "Display.h"
- #include "Timer.h"
- void main()
- {
- Timer0Init(); //中断初始化
- while(1)
- {
- Datapros();
- TaskProcess();
- KeyProcess();
- }
-
- }
- Displsy.c模块函数
- #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;//按键之前的状态
- bit keystay = 1; //按键现在的状态
- void DigDisplay()
- {
- static unsigned char 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()//时间自加函数
- {
- sec++; //每一秒钟执行一次
- 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)//判断按键现在状态与之前状态是否有变化
- {
- if(keyback==0) //如果之前状态是零,则说明按键有触发
- {
- keymin++;
- if(keymin==60)
- keymin=0;
- }
- }
- min=keymin;
- keyback = keystay; //按键状态赋值
- }
- 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,则按键状态置为0(按下)
- {
- keystay = 0;
- }
- if(keydelay==0xff)
- {
- keystay = 1;
- }
-
- }
- void ClockProcess()//闹钟判断函数
- {
- unsigned char nhour = 20,nmin = 52,nsec = 1; //定义变量
- if((nsec==sec)&&(nmin==min)&&(nhour==hour))
- {
- beep=~beep;
- D1 = 0;
- }
- if(sec==nsec+2)//两秒钟之后在发生变化
- {
- beep=~beep;
- D1 = 1;
- }
-
- }
- Timer.c模块函数
- #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 //中断函数运行函数数量 [/size][/font][/backcolor][/color][/align]
- TH0 = 0Xfc; //给定时器赋初值,定时100us
- TL0 = 0x18;
- for(i = 0;i<COUNT;i++) //循环扫描,判断哪一个任务定时时间已到
- {
- if(TaskCount[i].Time)
- {
- TaskCount[i].Time--; //如果定时时间已到则清零,标记置一
- if(TaskCount[i].Time==0)
- {
- TaskCount[i].Flag = 1;
- TaskCount[i].Time = TaskCount[i].ItvTime; // 恢复计时器值,从新下一次
- }
- }
- }
- }
- void TaskProcess() //处理函数
- {
- unsigned char i;
- for (i=0; i<COUNT; i++) // 循环判断那一个任务需要运行,逐个任务时间处理
- {
- if (TaskCount[i].Flag) // 时间不为0
- {
- TaskCount[i].Function(); // 运行任务
- TaskCount[i].Flag = 0; // 标志清0
- }
- }
- }
复制代码
|