标题:
单片机时间片轮询法(数码管显示—中断消抖)源程序
[打印本页]
作者:
白州小李
时间:
2019-12-3 13:23
标题:
单片机时间片轮询法(数码管显示—中断消抖)源程序
时间片轮询法(数码管显示——中断消抖)
本文章是关于运用时间片轮询法(前后台系统),完成对时钟的简单控制,同时通过中断完成对按键的消失抖,显示程序中静态变量变量的定义是关键,
对按键消抖应该是未按下(抬起——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, 下载次数: 49)
下载附件
2019-12-3 13:22 上传
主函数
#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
}
}
}
复制代码
作者:
lanxichang
时间:
2021-4-9 23:29
没有贴出来原程序啊
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1