用Delay消抖时会导致主程序中的一些进程受到影响,所以在这里借鉴江科大使用定时器扫描按键状态进行消抖的方法。在实际使用中加入了长按功能
按键驱动代码key.c
#include <REGX52.H>
unsigned char Key_KeyNumber,KeyTime,KeyCount,i;
unsigned int times;
/**
* @brief 获取按键键码
* @param 无
* @retval 返回值Temp暂存按下按键的键码,范围:0-6共七位 其中键码值为0时表示无按键按下
*/
unsigned char Key(void)
{
unsigned char Temp=0;
Temp=Key_KeyNumber;
Key_KeyNumber=0;
return Temp;
}
/**
* @brief 获取当前按键的状态,无消抖及松手检测
* @param 无
* @retval 返回值KeyNumber表示按下按键的键码,范围:0-6共七位 其中键码值为0时表示无按键按下
*/
unsigned char MatrixKey_GetState()
{
unsigned char KeyNumber=0;
P3=0Xff;
P3_4=0;
if(P3_5==0){KeyNumber=6;}
if(P3_6==0){KeyNumber=4;}
if(P3_7==0){KeyNumber=5;}
P3=0Xff;
P3_3=0;
if(P3_5==0){KeyNumber=3;}
if(P3_6==0){KeyNumber=1;}
if(P3_7==0){KeyNumber=2;}
return KeyNumber;
}
/**
* @brief 按键驱动函数,在中断中调用
* @param 无
* @retval 无
*/
void Key_Loop(void)
{
static unsigned char NowState,LastState;
LastState=NowState;
NowState=MatrixKey_GetState(); //更新键码值
if(LastState==1 || LastState==2 || LastState==3 || LastState==4) //1-4号键单击功能
{
if(NowState==0)
{
Key_KeyNumber=LastState;
}
}
if(LastState==5 || LastState==6)
{
i++;
times++;
if(NowState==0)
{
KeyCount=i;
i=0;
if(LastState==5 && KeyCount<=50){Key_KeyNumber=5;KeyCount=0;}//短按时间小于1s
else if(LastState==6 && KeyCount<=50){Key_KeyNumber=6;KeyCount=0;}//长按时间大于1s
if(LastState==5 && KeyCount>=100){Key_KeyNumber=9;KeyCount=0;}//短按时间小于1s
else if(LastState==6 && KeyCount>=100){Key_KeyNumber=10;KeyCount=0;}//长按时间大于1s
}
if(NowState)
{
if(times>=50)
{
KeyTime++;
if(KeyTime>=10)
{
if(LastState==5 && NowState==5){Key_KeyNumber=7;KeyTime=0;}//检测长按松手,防止长按后又判定到短按
else if(LastState==6 && NowState==6){Key_KeyNumber=8;KeyTime=0;}
}
}
}
else
{
times=0;
}
}
}
//定时器中断函数
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
T0Count++;
if(T0Count>=20)
{
T0Count=0;
Key_Loop();//每隔20ms扫描一次
}
}
定时器0初始化代码(20ms扫描一次按键状态)
#include <REGX52.H>
/**
* @brief 定时器0初始化,1毫秒@12.000MHz
* @param 无
* @retval 无
*/
void Timer0Init(void)
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1;
EA=1;
PT0=0;
}
主函数main.c
#include <REGX52.H>
#include "Timer0.h"
#include "Key.h"
unsigned char KeyNum;
void main()
{
Timer1Init();
while(1)
{
KeyNum=Key(); //获取独立按键键码
if(KeyNum==1) //如果K1按键按下
{
//执行相应动作
}
}
}