论坛元老 
   
	- 积分
 - 4095
 
        - 金钱
 - 4095 
 
       - 注册时间
 - 2015-12-21
 
      - 在线时间
 - 893 小时
 
 
 
 | 
 
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; 
} 
 
 |   
 
 
 
 
 
 |