利用定时计数器实现一个定时的变量累加。
2-1 中用while实现变量累加,随着程序中任务的增加,那么数码管动态刷新的时间就会增加 ,按键扫描累加的时间就会发生变化。
改进:将按键扫描和数码管动态刷新放到定时计数器里面,人机交互界面可以用该程序框架编写。
以后主要针对功能代码,而不用关心数码管的显示情况和按键识别。
如本程序中设定2ms进入一次按键扫描,如果我们想要实现10ms的延时消抖,那么我们可以在按键扫描函数中设定累加值key1_cnt > KEY_DE LAY_TIME,将KEY_DE LAY_TIME宏定义为5,满足条件key1_cnt > KEY_DE LAY_TIME,也就是key1_cnt为11时满足条件,则 key1_lock_flag = 1; //自锁标志置1,代表按键按下,防止按键多次触发
KeyNum = 1; //赋键值编码
其他按键同理,最终实现定时器实现变量累加的非阻塞延时
main.c
#include<reg51.h>
#include "Key.h"
#include "display.h"
#include"time.h"
void Key_Service();
void Dis_Service();
unsigned int NumCnt;
void main()
{
Timer0Init();//定时器初始化
while(1){
Key_Service();
Dis_Service();
//Display(); //由于Display在定时器中执行了
}
}
void Dis_Service()
{
LEDBuf[0] = NumCnt / 1000; //取千位
LEDBuf[1] = NumCnt / 100%10; //取百位
LEDBuf[2] = NumCnt / 10 % 10; //取十位
LEDBuf[3] = NumCnt % 10; //取个位
}
void Key_Service()
{
//switch(Key_Scan()){
switch(Key_Val){ //全局变量Key_Val
case 0:break;
case 1:NumCnt++;if(NumCnt > 9999)NumCnt = 0;break;
case 2:NumCnt--;if(NumCnt > 9999)NumCnt = 9999; break;
case 3:NumCnt=0; break;
case 4:NumCnt=88;break;
default:break;
}
}
time.c
#include"display.h"
#include"Key.h"
接着以上代码,编写中断服务函数
注意消隐(GPIO_DIG = 0x00)的位置需要调整至分支开头
用定时计数器取代Delaxms延时函数,每隔2ms执行一个动态刷新的分支
按键扫描:带返回值
time.c需要定义一个全局变量来接收扫描值,然后将该值传递给主程序处理
unsigned char Key_Val = 0; //全局变量
void timer0_ISR() interrupt 1 //每隔2ms进入定时中断
{
TR0 = 0;
Display();//数码管定时刷新,这样主程序就可以注释掉动态刷新函数了
Key_Val = Key_Scan();//Key_Val是全局变量
TL0 = 0x30; //设置定时初始值
TH0 = 0xF8; //设置定时初始值
TR0 = 1;
}
time.h
#ifndef __TIME_H__
#define __TIME_H__
#include <reg51.h>
extern unsigned char Key_Val;//外部声明
void Timer0Init(void);
#endif
key.c
#include "Key.h"
#include "delay.h"
unsigned char key1_lock_flag;//自锁标志,为的是去掉松手等待
unsigned char key1_cnt;//非阻塞延时代替阻塞延时,需要用到变量累加
unsigned char key2_lock_flag;//自锁标志,为的是去掉松手等待
unsigned char key2_cnt;//非阻塞延时代替阻塞延时,需要用到变量累加
unsigned char key3_lock_flag;//自锁标志,为的是去掉松手等待
unsigned char key3_cnt;//非阻塞延时代替阻塞延时,需要用到变量累加
unsigned char key4_lock_flag;//自锁标志,为的是去掉松手等待
unsigned char key4_cnt;//非阻塞延时代替阻塞延时,需要用到变量累加
unsigned char Key_Scan(){
unsigned char KeyNum = 0;
//如果按键不稳定,产生抖动,当key1_cnt加到88,突然抖动,那么key1_cnt清零,重新计数,实现消抖的作用。
if(KEY1)//如果没有按键按下,按键处于高电平
{
//如果没有按键按下,则给他清零
key1_lock_flag = 0;//清零自锁标志
key1_cnt = 0; //清零计数标志
}
else if(!key1_lock_flag && KEY1 == 0){
key1_cnt++; //累计按键消抖延时次数,主循环while每执行一次,key1_cnt加一
if(key1_cnt > KEY_DE LAY_TIME)//KEY_DELAY_TIME的大小可以调节按键的灵敏度,取决于任务多少个,每个任务的执行时间是多少
{
key1_cnt = 0; //清零计数变量
key1_lock_flag = 1; //自锁标志置1,代表按键按下,防止按键多次触发
KeyNum = 1; //赋键值编码
}
}
if(KEY2)//如果没有按键按下,按键处于高电平
{
//如果没有按键按下,则给他清零
key2_lock_flag = 0;//清零自锁标志
key2_cnt = 0; //清零计数标志
}
else if(!key2_lock_flag && KEY2 == 0){
key2_cnt++; //累计按键消抖延时次数
if(key2_cnt > KEY_DE LAY_TIME)//KEY_DELAY_TIME的大小可以调节按键的灵敏度
{
key2_cnt = 0; //清零计数变量
key2_lock_flag = 1; //自锁标志置1,代表按键按下,防止按键多次触发
KeyNum = 1; //赋键值编码
}
}
if(KEY3)//如果没有按键按下,按键处于高电平
{
//如果没有按键按下,则给他清零
key3_lock_flag = 0;//清零自锁标志
key3_cnt = 0; //清零计数标志
}
else if(!key3_lock_flag && KEY3 == 0){
key3_cnt++; //累计按键消抖延时次数
if(key3_cnt > KEY_DE LAY_TIME)//KEY_DELAY_TIME的大小可以调节按键的灵敏度
{
key3_cnt = 0; //清零计数变量
key3_lock_flag = 1; //自锁标志置1,代表按键按下,防止按键多次触发
KeyNum = 1; //赋键值编码
}
}
if(KEY4)//如果没有按键按下,按键处于高电平
{
//如果没有按键按下,则给他清零
key4_lock_flag = 0;//清零自锁标志
key4_cnt = 0; //清零计数标志
}
else if(!key4_lock_flag && KEY1 == 0){
key4_cnt++; //累计按键消抖延时次数
if(key4_cnt > KEY_DE LAY_TIME)//KEY_DELAY_TIME的大小可以调节按键的灵敏度
{
key4_cnt = 0; //清零计数变量
key4_lock_flag = 1; //自锁标志置1,代表按键按下,防止按键多次触发
KeyNum = 1; //赋键值编码
}
}
}
Key.h
#ifndef __KEY_H__
#define __KEY_H__
#include <reg51.h>
//#define KEY_DELAY_TIME 100
#define KEY_DELAY_TIME 5 //由于定时器每2ms进入一次计数,此时需要将100改为5,普遍消抖时间是10ms-20ms
sbit KEY1 = P3^0;
sbit KEY2 = P3^1;
sbit KEY3 = P3^2;
sbit KEY4 = P3^3;
unsigned char Key_Scan();
#endif
问题:按键按下一次不是加1次,而是很多次(全局变量作为键值,进入case后需要清零)
按键识别没问题,可能功能代码有问题
由于Key_Val是全局变量
全局变量一旦赋值,他就会占用内存
需要进入case 后将Key_Val清零,否则它会卡在某个case一直进行运算操作,直到下一次按键按下。
void Key_Service()
{
//switch(Key_Scan()){
switch(Key_Val){ //全局变量Key_Val
case 0:break;
case 1:Key_Val = 0;NumCnt++;if(NumCnt > 9999)NumCnt = 0;break;
case 2:Key_Val = 0;NumCnt--;if(NumCnt > 9999)NumCnt = 9999; break;
case 3:Key_Val = 0;NumCnt=0; break;
case 4:Key_Val = 0;NumCnt=88;break;
default:break;
}
}