henry 发表于 2012-3-2 16:21:06

请教马潮老师:矩阵键盘+线翻转+状态机 调试问题

请教马潮老师以及各位大侠:

之前看马潮老师有关矩阵键盘的状态机方法的讲解,刚好有个设计中有涉及到矩阵键盘(3*3矩阵,实际用到7个按键),只不过还需要识别按键的长短按,我就把马老师的程序改了改,结果在调试的时候按键没有反应!硬件应该是没有问题的,我用延时消抖的方式已经能够识别7个按键了,只是长短按键的识别不好设计,我才改用状态机,并用定时器定时扫描的方式来设计,可能我的代码有问题吧,下面贴上代码,还请各位大侠指教!!!

/*********************************************************/
/* 读取当前键值:线反转法                              */
/*********************************************************/

unsigned char MatrixKeyRead_LineReverse(void)
{
unsigned char keycodeC = 0;
unsigned char keycodeR = 0;

DDRD &= 0x03;//这里是为了不影响串口RXD和TXD的设置

DDRD |= 0x1c;// PD7~PD5输入,PD4~PD2输出

PORTD &= 0x03;//同样是为了不影响串口RXD和TXD的设置

PORTD |= 0xe0;// PD7~PD5内部上拉,PD4~PD2输出低电平

keycodeC = PIND & 0xe0;

DDRD &= 0x03;

DDRD |= 0xe0;// PD7~PD5输出,PD4~PD2输入

PORTD &= 0x03;

PORTD |= 0x1c;// PD7~PD5输出低电平,PD4~PD2内部上拉

keycodeR = PIND & 0x1c;

return (keycodeC | keycodeR);
}

/*********************************************************/
/* 按键扫描:状态机                                    */
/*********************************************************/

void MatrixKeyScan(stKeyReturn * ps_keyReturn)
{
static etKeyState e_keyState = KEY_STATE_KEY_NO_PRESS;

etKeyCode e_keyCode = KEY_NO_PRESS;

etKeyCode e_keyCodeTmp = KEY_NO_PRESS;

static unsigned char keyHoldTimeCnt = 0;

e_keyCode = MatrixKeyRead_LineReverse();
       
        switch(e_keyState)
        {
                case KEY_STATE_KEY_NO_PRESS:                                // 按键状态0:无按键
                {
                        if(e_keyCode != KEY_NO_PRESS)                        // 有键按下,转入按键状态1:按键消抖
                        {                               
                                e_keyState = KEY_STATE_KEY_FILTER;       
                        }

                        break;
                }

                case KEY_STATE_KEY_FILTER:                                        // 按键状态1:按键消抖
                {
                        if(e_keyCode != KEY_NO_PRESS)                        // 有键按下,确定按键,打开计数器,转入按键状态2:按键延时
                        {
                                keyHoldTimeCnt = 0;

//                                s_keyReturn.keyCode = e_keyCode;

                                e_keyCodeTmp = e_keyCode;

                                e_keyState = KEY_STATE_KEY_HOLD_TIME;
                        }
                        else                                                                        // 无键按下,转入按键状态0:无按键
                        {
                                e_keyState = KEY_STATE_KEY_NO_PRESS;
                        }

                        break;
                }

                case KEY_STATE_KEY_HOLD_TIME:                                // 按键状态2:按键延时
                {
                        if(e_keyCode == KEY_NO_PRESS)                        // 如果按键已经释放,确定为短按键及其键值,转入状态0:无按键
                        {
                                ps_keyReturn->keyCode = e_keyCodeTmp;
                               
                                ps_keyReturn->keyType = KEY_TYPE_KEY_SHORT_PRESS;

                                e_keyState = KEY_STATE_KEY_NO_PRESS;        
                        }
                        else if((++ keyHoldTimeCnt) > 100)                // 如果计时超过规定时间仍然没有释放,转入状态3:长按键释放
                        {
//                                s_keyReturn.keyType = KEY_TYPE_KEY_LONG_PRESS;

                                e_keyState = KEY_STATE_KEY_RELEASE;
                        }

                        break;
                }

                case KEY_STATE_KEY_RELEASE:                                        // 按键状态3:长按键释放
                {
                        if(e_keyCode == KEY_NO_PRESS)                        // 如果按键已经释放,确定为长按键以及相应键值,转入状态0:无按键
                        {
                                ps_keyReturn->keyCode = e_keyCodeTmp;
                               
                                ps_keyReturn->keyType = KEY_TYPE_KEY_LONG_PRESS;
                               
                                e_keyState = KEY_STATE_KEY_NO_PRESS;
                        }

                        break;
                }

                default:break;
        }
}

ISR(TIMER0_OVF_vect)
{       
        TCNT0 = 0x28;

        keyScanOnceFlg = 1;
}
页: [1]
查看完整版本: 请教马潮老师:矩阵键盘+线翻转+状态机 调试问题