论坛元老
- 积分
- 4015
- 金钱
- 4015
- 注册时间
- 2015-12-21
- 在线时间
- 887 小时
|
1金钱
请教!这个矩阵键盘不用中断如何修改?
/*
程序功能:
K1单击时num+1;长击num+2;
K2单击时num-1;长击num-2;
K5连击按键 按着num+1;
K6连击按键 按着num-1;
无按键时间4s led亮;有按键,led灭。
*/
//支持单击(短击)、连击,长击,无击
//长击时间到后,立即执行;短击释放后执行
//按键方式(单击,长击)、(只支持单击)、(连击)
//连击实际上包含了单击
#include "reg51.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
#define NOP() _nop_()
#define KeyPIN P1
sbit led=P3^7;
uchar num;
uchar key_code[]= {0x7e,0x7d,0x7b,0x77,0xbe,0xbd,0xbb,0xb7,0xde,0xdd,0xdb,0xd7,0xee,0xed,0xeb,0xe7};
struct
{
uchar state;//按键状态 0-等待阶段;1-闭合抖动阶段;2-有效闭合阶段;3-释放阶段
uchar type;//0-无按键或者按键已经响应 ;1-单击 ;2-连击 ;3-长击;4-无击
uchar detect;//按键检测标志 1为检测到按键
uchar value;//当前键值
uchar backvalue;//备份键值
uchar disable;//按键禁止响应标志:按键执行过,则标志为1.主要用于长击。
uchar scan_en;//按键扫描标志 1为允许扫描
uchar tmr_no;//无键计数器,用于无击。
uchar cnt_press;//按键闭合计数器,用于长击。
uchar delay_con;//连击响应延时时间,用于连击。
#define AN_XD_DL 2//AN_XD_DL*定时器中断20ms
#define AN_LA_DL 10//AN_LA_DL*20ms
#define AN_CJ_DL 5//长击所需时间:AN_CJ_DL*AN_LA_DL*20ms
#define KEY_IDLE 0//按键等待阶段
#define KEY_IS_DOWN 1//闭合抖动阶段
#define KEY_DOWN 2//有效闭合阶段
#define KEY_IS_UP 3//释放阶段
#define NoKey 0//无键
#define NoKeyTMR 200//无键所需时间:NoKeyTMR*20ms
} key;
unsigned char KeyScan(void);
void KeyInit(void);
void KeyProcess(void);
void KeyShortPress(void);//短击 单击
void KeyLongPress(void);//长击
void KeyContinuePress(void);//连击
void KeyNoPress(void);//无击
void KeyAction(void);//根据按键类型动作 散转程序
void main()
{
TCON=0x00;
IE=0x84;
TMOD=0x01;
TH0=0xB1;
TL0=0xE0;
ET0=1;
TR0=1;
EA = 1;
while(1)
{
KeyPIN=0x0f;
KeyProcess();
KeyAction();
P0=num/10;
P2=num%10;
}
}
//键盘扫描方法,反转法
uchar KeyScan(void)
{
uchar temp,keyval=0;
KeyPIN = 0x0f;
if (KeyPIN != 0x0f)
{
temp=KeyPIN;
KeyPIN = 0xf0;
temp|=KeyPIN;
keyval=1;
while (key_code[keyval-1] != temp) //把特征码转换为键号
{
keyval++;
if(keyval>0x0f)
{
break;
}
}
}
return keyval;
}
void KeyProcess()
{
switch(key.state)
{
case KEY_IDLE://等待阶段
{
key.disable=0;
key.delay_con=AN_XD_DL;
key.cnt_press=0;
if(key.detect)//有按键才允许扫描
{
key.tmr_no=0;//有键按下,无键计数器清零
key.type=0;
key.detect=0;
if(key.scan_en)
{
key.scan_en=0;
key.state=KEY_IS_DOWN;
}
}
else
{
if(key.tmr_no==NoKeyTMR)
{
key.type=4;
}
}
}
break;
case KEY_IS_DOWN:
{
key.tmr_no=0;
if(key.scan_en)
{
key.scan_en=0;
key.value=KeyScan();
if(key.value==key.backvalue)
{
key.state=KEY_DOWN;
}
else
{
key.backvalue=key.value;
}
}
}
break;
case KEY_DOWN:
{
key.tmr_no=0;
if(key.scan_en)
{
key.scan_en=0;
key.backvalue=key.value;//备份当前键值供释放后 单击 使用
key.value=KeyScan();
key.delay_con--;
if(key.delay_con==0)
{
key.delay_con=AN_LA_DL;
key.cnt_press++;
if(key.cnt_press>AN_CJ_DL)
{
if(!key.disable)//长击执行过一次后,如不释放按键,不执行。
{
key.type=3;
}
else
{
key.type=0;
}
}
else
{
key.type=2;
}
}
if(key.value==NoKey)
{
key.state=KEY_IS_UP;
}
}
}
break;
case KEY_IS_UP:
{
key.tmr_no=0;
if(!key.disable)//避免长击释放后 继续执行单击
{
key.type=1;
}
key.state=KEY_IDLE;
}
break;
}
}
void KeyAction(void)
{
switch(key.type)
{
case 1:
{
KeyShortPress();
}
break;
case 2:
{
KeyContinuePress();
key.type=0;
}
break;
case 3:
{
KeyLongPress();
}
break;
case 4:
{
KeyNoPress();
}
break;
}
}
void KeyNoPress(void)
{
led=0;
}
void KeyShortPress(void)
{
led=1;
switch(key.backvalue)
{
case 1:
num++;
break;
case 2:
num--;
break;
}
}
void KeyContinuePress(void)
{
led=1;
switch(key.backvalue)
{
case 5:
num++;
break;
case 6:
num--;
break;
}
}
void KeyLongPress(void)
{
led=1;
switch(key.backvalue)
{
case 1:
num+=2;
key.disable=1;
key.type=0;
break;//此处key.disable和key.type必须这样处理
case 2:
num-=2;
key.disable=1;
key.type=0;
break;
default:
key.type=2;//因为长击是在按下后时间足够后就触发的,所以为避免连击和长击冲突,必须加此句
}
}
void timer0() interrupt 1 using 1 //12M晶振 20ms中断
{
TH0=0xB1;
TL0=0xE0;
key.tmr_no++;
if(key.detect)
{
key.scan_en=1; //有键按下才允许扫描
}
}
void EXT_INT() interrupt 2 using 1
{
key.detect=1;
}
|
|