1、独立连接式键盘每一个按键占用一个I/O引脚。优点是结构简单,使用方便;缺点是随着按键数的增加,被占用的I/O口线也将增加。所以不适合在按键较多的情况下使用。如图1所示。
2、矩阵式键盘适合采用动态扫描的方式进行识别。优点是节省端口,缺点是编程麻烦。适合按键较多的场合。如图2所示。

图1 独立式键盘


图2 矩阵式键盘
二、矩阵式键盘又可以分为编码式键盘和非编码式键盘
1、编码键盘能够由硬件自动提供与被按键对应的ASCII码或其它编码。内部设有键盘编码器,能识键、生成键码、去抖、防串键。
2、非编码键盘则仅提供行和列的矩阵,其硬件逻辑与按键编码不存在严格的对应关系,而要由所用的程序来确定。通常只提供键盘矩阵,按键的识别、键码的提供由软件来完成。
1、编码键盘能够由硬件自动提供与被按键对应的ASCII码或其它编码。内部设有键盘编码器,能识键、生成键码、去抖、防串键。
2、非编码键盘则仅提供行和列的矩阵,其硬件逻辑与按键编码不存在严格的对应关系,而要由所用的程序来确定。通常只提供键盘矩阵,按键的识别、键码的提供由软件来完成。
三、非编码矩阵键盘扫描
对于编码式键盘,可以直接通过其预留的接口读取按键值即可。对于非编码式矩阵键盘,需要自己扫描得到按键的值,通常采用的方法是行扫描法和线反转法两种方法。
(1)行扫描法
行列扫描法可以分两步:
step 1.判断是否有按键按下进行全扫描,将所有行线置成低电平;然后扫描全部列线,如果扫描的列值全是高电平,则说明没有任何一个键被按下;如果读入的列值不是全1,则说明有键按下。在只有单键的情况并可以得到列线值。
step 2.判断那一行的按键被按下用逐行扫描的方法确定哪一个键被按下。先扫描第一行,即置该行为低电平,其他行为高电平,然后检查列线,如果某条列线为低电平,则说明第一行与该列相交的位置上的按键被按下;如果所有列线全是高电平,则说明第一行没有键被按下,接着扫描第二行,以此类推,直到找到被按下的键。
(2)线反转法
线反转法需要两步:
step 1.将列线作为输出线,行线作为输入线。置输出线全部为0,此时行线中呈低电平0的为按键所在行,如果全部都不是0,则没有按键按下。
step 2.将行线作为输出线,列线作为输入线。置输出线全部为0,此时列线呈低电平的为按键所在的列。这样,就可以确定了按键的位置(X,Y)。
四、行扫描法和线反转法的区别
1、线反转法需要接键盘的IO口必须是双向的,而行扫描法列线输入,行线输出,单向IO就可以完成。
2、线反转法要求键盘的两端都上拉(如图3所示),如果IO可以支持内部上拉模式的话可以在软件上设置寄存器开启上拉模式(对于Atmega8需要设置DDRxn,PORTxn,PUD(SFIOR))。而行扫描法只需要列线上拉就可以了。
图3
单键行扫描方式的代码如下:
//single key scan function
void KeyScan()
{
U8 data=0xFF;
U8 tmp=0xFF;
U8 line,row;
int i=0,j=0;
unsigned char SendBuffer[2];
SetDataLow(0xFF); //set line high level
tmp = GetDataLow(); //get the key
if(0xFF!=tmp)
{
Delay(100);
tmp = GetDataLow();
if(tmp==0xFF) //avoid dithering
{
//putchar(0x99);
return;
}
line = CheckBit(~tmp);
for(i=0; i<8; i++) //scan begin here
{
SetDataLow(i);
data = GetDataLow(); //get the key
if(data == tmp)
{
row=i;
break;
}
else
{
}
}
SendKeyDownCode(KeyMap[line][row]);
while(0xFF!=GetDataLow()); //wait until this key is up
SendKeyUpCode(KeyMap[line][row]);
}
}
No comments:
Post a Comment