1、删减了《51单片机——独立按键、矩阵按键多种方案1.1》里的一些不怎么用的代码。
2、添加了逐行扫描按键(需要定时器20毫秒配合使用)。
3、支持按键短按、长按、一直按,代码里只做了短按处理,如要处理长按和一直按只需添加相应的代码即可。
4、按键处理我只点亮led灯了,需要其它功能自行添加即可。
5、最大优化我觉得是没有一个delay延迟。
备注:按键处理及按键扫描放入定时器中断里即可。
#ifndef __KEY2_H__
#define __KEY2_H__
extern void key_hang(void);//按键行扫描,需要配合定时器
extern void key_process(void);//处理按键对应的结果
#endif //!__KEY2_H__
#include "REG52.H"
#include "led.h"
#define hang P3
//矩阵按键真值表4行*4列判断是哪个按键被按下
static unsigned char code key_true[4][4] = {
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16
};
void key_hang(void)//按键行扫描,建议20毫秒扫一下
{
static unsigned char i = 0;
i++;
switch (i)//共计4行,低电平扫描
{
case 1:hang = 0xfe;break;
case 2:hang = 0xfd;break;
case 3:hang = 0xfb;break;
case 4:hang = 0xf7;i = 0;break;
default:hang = 0xff;i = 0;
break;
}
}
static unsigned char key16_3(void)//每隔10毫秒30毫秒50毫秒.....进来一次
{
static unsigned char key_time = 9;//按键次数或时间初值为9
static unsigned char hang_true =0;
static unsigned char lie_true = 0;
//if (Time_20ms == 1)//如果20ms时间到的话就开始判断是否有按键按下
//{
if ((hang & 0xf0) != 0xf0)//如果有按键按下
{
hang_true = hang & 0x0f;//计算4行的当前值
lie_true = hang & 0xf0;//计算4列的当前值
key_time++;//当有按键被按下,key_time++一次时间就加20毫秒,第一次++的时候时间记为0毫秒
if (key_time < 5) --key_time;//避免数据加的太多溢出,防止用户一直按
if (key_time > 150)//表示长按且大于3000毫秒
{
//如果有按键按了3秒以上,在这里先不处理这么久的
key_time = 9;//恢复初始值
return 0;
}
return 0;
}
else//判断一下当前按键值是否为短按
if (10 < key_time < 150)//表示短按且时间大于100毫秒小于3秒
{
switch (hang_true)
{
case 0x0e:hang_true = 0;break;
case 0x0d:hang_true = 1;break;
case 0x0b:hang_true = 2;break;
case 0x07:hang_true = 3;break;
default:
break;
}
switch (lie_true)
{
case 0xe0:lie_true = 0;break;
case 0xd0:lie_true = 1;break;
case 0xb0:lie_true = 2;break;
case 0x70:lie_true = 3;break;
default:
break;
}
key_time = 9;//恢复初始值,好进行下次按键判断
return key_true[hang_true][lie_true];
}
return 0;
//}
//return 0;
}
void key_process(void)//处理按键对应的方法
{
switch (key16_3())
{
case 0: break;//默认没有按键按下将会返回0
case 1: LED_Admin_EN(0x7f);break;//led灯从左到右亮
case 2: LED_Admin_EN(0xbf);break;
case 3: LED_Admin_EN(0xdf);break;
case 4: LED_Admin_EN(0xef);break;
case 5: LED_Admin_EN(0xf7);break;
case 6: LED_Admin_EN(0xfb);break;
case 7: LED_Admin_EN(0xfd);break;
case 8: LED_Admin_EN(0xfe);break;//led灯从左到右亮
case 9: LED_Admin_EN(0xfe);break;//led灯从右到左亮
case 10: LED_Admin_EN(0xfd);break;
case 11: LED_Admin_EN(0xfb);break;
case 12: LED_Admin_EN(0xf7);break;
case 13: LED_Admin_EN(0xef);break;
case 14: LED_Admin_EN(0xdf);break;
case 15: LED_Admin_EN(0xbf);break;
case 16: LED_Admin_EN(0x7f);break;//led灯从右到左亮
default:
break;
}
}