2010-10-16 77 views
2

我有一个设备有9个键就像一个普通的手机。 我想打印正常的字母如ABCD使用这9个键完全按照手机让你这样做。逻辑9键键盘打印QWERTY键

这是一个嵌入式系统编程项目。我无法弄清楚实现这个功能的逻辑。

我通过轮询而不是中断来检测密钥。

有人可以帮忙吗?如果您能指出相关资源,我将不胜感激。

回答

6

这是一个小键盘解码演示程序,应该可以帮助您顺利完成任务。您需要重新编写硬件的主要扫描例程。另外,连续两次选择相同的数字会有某种超时。你也应该有一点麻烦搞清楚如何添加大写,标点符号和Meta键支持...

#include <stdio.h> 

#define NUM_KEYS 10 
#define NUM_PHASES 6 

char KeyMap[NUM_KEYS][NUM_PHASES] = 
    { { '0', 0, 0, 0, 0, 0 }, 
     { '1', 0, 0, 0, 0, 0 }, 
     { '2', 'A', 'B', 'C', 0, 0 }, 
     { '3', 'D', 'E', 'F', 0, 0 }, 
     { '4', 'G', 'H', 'I', 0, 0 }, 
     { '5', 'J', 'K', 'L', 0, 0 }, 
     { '6', 'M', 'N', 'O', 0, 0 }, 
     { '7', 'P', 'Q', 'R', 'S', 0 }, 
     { '8', 'T', 'U', 'V', 0, 0 }, 
     { '9', 'W', 'X', 'Y', 'Z', 0 } }; 

char KeyGet() 
{ 
    char key; 

    /* do whatever it takes to scan your 
     keyboard and return the _numeric_ digit. */ 

    /* for this test simulate with console input */ 
    key = getc(stdin); 

    if ((key >= '0') && (key <= '9')) 
    { 
     key -= 0x30; 
    } 
    else 
    { 
     key = 0; 
    } 

    return key; 
} 

char DecodeKey(char NewKey, char *pOldKey, int *pPhase) 
{ 
    char ch = 0; 

    /* Validate Phase */ 
    if ((*pPhase < 0) || (*pPhase >= NUM_PHASES)) 
    { 
     *pPhase = 0; 
    } 

    /* see if a different key was pressed than last time */ 
    /* if it was then restart the phase counter */ 
    if (NewKey != *pOldKey) 
    { 
     *pPhase = 0; 
     *pOldKey = NewKey; 
    } 

    /* Validate Key */ 
    if ((NewKey >= 0) && (NewKey < NUM_KEYS)) 
    { 
     ch = KeyMap[(int)NewKey][*pPhase]; 

     /* if the phase position is NULL, just get the numeric digit */ 
     if (ch == 0) 
     { 
      *pPhase = 0; 
      ch = KeyMap[(int)NewKey][*pPhase]; 
     } 

     /* bump the phase */ 
     ++(*pPhase); 

     if (*pPhase >= NUM_PHASES) 
     { 
      *pPhase = 0; 
     } 
    } 

    return ch; 
} 

int main() 
{ 
    char nk;  /* new key */ 
    char ok = 0; /* old key */ 
    char c;   /* resulting character */ 
    int phase = 0; /* tracks the key presses */ 

    while (1) 
    { 
     /* get a key */ 
     nk = KeyGet(); 

     /* convert it to a character */ 
     c = DecodeKey(nk, &ok, &phase); 

     if (c != 0) 
     { 
      printf("%c", c); 
     } 
    } 

    return 0; 
} 
+0

键= GETC(标准输入);是阻止呼叫? – 2010-10-17 10:13:32

+0

@Akshar:是的,这是一个用于此演示的阻止呼叫。标准C没有非阻塞控制台输入库例程。实施者需要为实际目标编写一个自定义例程。 – 2010-10-17 11:18:09

1

要做到一个很好的设计,你需要一个键盘输入程序,可以告诉你何时按键已经被搁置了一段时间,并且当它们被释放了一段时间。在按下数字后的短时间内,应该将光标保持在新输入的字符上;如果再次按下相同的数字,则应该更改新输入的字符。如果输入另一位数字,则将选定数字设为“永久”,并将光标显示在新密钥的字符上。如果没有按键被按下一秒左右,请将光标移到下一个位置。如果在光标位于新输入的数字上时按下Enter键,只需前进光标即可。如果它在光标自动前进的大约1/4秒内被推入,则不执行任何操作。如果在光标不在字符上并且不仅仅是自动提前时被按下,请确认输入。

0

把你的控制器的6个引脚用于键盘P0-> P6。将你的3列P0-> P3和3行连接到P4-> P6。用代码将所有引脚拉高。通过在每列上设置低位来扫描每行。因此,通过获取特定的行和列,你将能够获得进入关键.. 希望你看这个..

0

适应Amardeep的回答是:

char KeyMap[NUM_KEYS][NUM_PHASES] = 
{ { '0', 0, 0, 0, 0, 0 }, 
    { '1', 0, 0, 0, 0, 0 }, 
    { '2', 'A', 'B', 'C', 0, 0 }, 
    { '3', 'D', 'E', 'F', 0, 0 }, 
    { '4', 'G', 'H', 'I', 0, 0 }, 
    { '5', 'J', 'K', 'L', 0, 0 }, 
    { '6', 'M', 'N', 'O', 0, 0 }, 
    { '7', 'P', 'Q', 'R', 'S', 0 }, 
    { '8', 'T', 'U', 'V', 0, 0 }, 
    { '9', 'W', 'X', 'Y', 'Z', 0 } }; 


//Gets the system time, e.g. as number of timer ticks since power up. You write this. 
sometype GetSystemTime(); 

//Checks if key has been pressed. Returns 0-9 if a key was pressed or -1 if no key was pressed. You write this. 
int KeyAvailable(); 

int main() 
{ 
const sometype PHASE_WAIT = somevalue; //The delay before shifting to the next character. 
char keyBuffer[BUFFER_SIZE]; //The input buffer. 
int keyIndex = 0; //The index into keyBuffer. 
int keyPress1 = -1, keyPress2; // keyboard inputs. 
sometype lastKeyPressTime; // The time a key was last pressed. 
int numKeyPresses; // The number of times the same key has been pressed this phase. 



/* keyboard processing loop. */ 
while (1) 
{ 
    if ((GetSystemTime() - lastKeyPressTime > PHASE_WAIT) && (-1 != keyPress1)) 
    { 
    // Phase timed out. Commit current character. 
    keyBuffer[keyIndex++] = KeyMap[keyPress1][numKeyPresses - 1]; 
    keyPress1 = -1; 
    } 
    if ((keyPress2 = KeyAvailable()) > -1) 
    { 
    // Key pressed. 
    lastKeyPressTime = GetSystemTime(); 
    if ((keyPress2 != keyPress1) && (-1 != keyPress1)) 
    { 
    // Different than last key. Commit current character and start a new one. 
    keyBuffer[keyIndex++] = KeyMap[keypress1][numKeyPresses - 1]; 
    numKeyPresses = 1; // Yes, I"m using 1-based indexing. Deal. 

    }else if (keyPress2 == keyPress1) 
    { 
    // Pressed same key multiple times in same phase. 
    numKeyPresses = ((numKeyPresses) % KEYMAPROWSIZE) + 1; 
    if (0 == KeyMap[keypress2][numKeyPresses - 1]) 
    { 
    //Loop back to first 'valid' character associated with this key. 
    numKeyPresses = 1; 
    } 
    }else // -1 == keyPress1 
    { 
    // Pressed new key. Start new phase. 
    numKeyPresses = 1; 
    } 
    keyPress1 = keyPress2. 
    } 
} 

}