用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;}//短按时间小于1selse if(LastState==6 && KeyCount<=50){Key_KeyNumber=6;KeyCount=0;}//长按时间大于1sif(LastState==5 && KeyCount>=100){Key_KeyNumber=9;KeyCount=0;}//短按时间小于1selse 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按键按下{//执行相应动作}}
}