1矩阵键盘的结构
下图是4 * 3矩阵键盘的,其中三列线连接到引脚P 1. 4-P 1. 6。四行线连接P 1. 0-P 1. 3引脚


2行扫描方法
首先,连接到三列线的I / O引脚P14-P16输出低电平,连接到四行线的I / O引脚P10-P13输出高电平。当不按任何按钮时,连接到四行线的I / O引脚将读取所有高电平;反之,当按下按钮时,由于按钮所在的行线已连接到列线,因此该行线将被拉低至低电平。此时,读取连接到行线的引脚P10-P13将不再是高电平,因此可以判断为按下了按钮。判断按键被按下后,使用逐列扫描方法获取按键的键值。
逐列扫描方法的原理是将列线一个接一个地设置为低电平并读取行线。如果某个行线为低电平,则表示该行线设置为低功耗。按下扁列线相交处的键,可以获取该键的键值。

#define keyboard P1 //四条行线三条列线所连接的IO口
unsigned char Check_Keyboard()
{
unsigned char row_scan_code=0x01; //行扫描码
unsigned char col_scan_code=0xEF;//列扫描码
unsigned char keycode; //按键键值
unsigned char i,x,j;
//可以做一个消抖处理
for(i=0;i<3;i++)//逐列扫描,将列线逐列拉低
{
keycode=i+1;
keyboard=col_scan_code;
x=keyboard; //读取行线状态
for(j=0;j<4;j++)//逐行扫描
{
if(!(x&row_scan_code))//说明对应行的按键按下,使行线被拉低
{
keycode+=3*j;
//如果按键还未释放,则仍有行线被拉至低电平
while((keyboard&0x0f)!=0x0f);//等待按键释放
P1=0x0F; //恢复原状态,为下次按键做准备
return keycode; //已检测到按键键码,返回
}
else
row_scan_code=_crol_(row_scan_code,1);
}
col_scan_code=_crol_(col_scan_code,1);//左移一位,将下一列线拉低
row_scan_code=0x01;//重置行扫描码,为下一行扫描作准备
}
keycode=0;//没有按键按下,键值记为0
return keycode;
}
三行反转方法
上面的逐列扫描方法比较麻烦,并且在实际的单芯片系统中更常使用行反转方法。

线反转方法的原理是:首先,使端口P1的高四位输出高电平,并使端口P1的低四位输出低电平。此时,键盘的行线被拉高,而列线被拉低。如果按下按钮,则特定的行线将被拉低。此时,读取P1端口的高四位,并且所有读取将不再为高,表明已按下按钮。 (在判断是否有按钮按下时,行反转方法与逐行扫描方法一致。)根据连接到I / O端口的值为0的行行,按下按钮所在的行。接下来,将端口P1的高四位输出为低电平,将端口P1的低四位输出为高电平(即与最后一个输出相反的电平,因此称为线路反转)。如果按下按钮,此时将读取P1端口的低四位,并且读取将不再是高电平。根据连接到I / O端口的值为0的列线,可以判断按键是哪一列。结合按钮的行线和列线可以唯一地确定按钮的位置,然后获取按钮的键值。
//@brief:判断4*4矩阵键盘是否有键可靠按下,高4位口接行线,低四位口接列线
//@retval:当有键可靠按下时返回1-16的键值,否则返回0
#define keyboard P1
unsigned char Check_Keydown()
{
unsigned char KeyValue=0;
keyboard=0x0f;
if(keyboard!=0x0f)//如果按键按下
{
delay_ms(10);//延时10ms消抖
if(keyboard!=0x0f)//按键确实按下
{
//判断按键所在列,以所在列的第一行的按键键值赋给KeyValue
keyboard=0X0F;
switch(keyboard)
{
case(0X07): KeyValue=1;break; //第一列按下
case(0X0b): KeyValue=2;break; //第二列按下
case(0X0d): KeyValue=3;break; //第三列按下
case(0X0e): KeyValue=4;break; //第四列按下
}
//判断按键所在行
keyboard=0XF0;
switch(keyboard)
{
case(0X70): KeyValue=KeyValue;break; //第一行按下
case(0Xb0): KeyValue=KeyValue+4;break; //第二行按下
case(0Xd0): KeyValue=KeyValue+8;break; //第三行按下
case(0Xe0): KeyValue=KeyValue+12;break; //第四行按下
}
while(keyboard!=0xf0); //按键松手后退出
return KeyValue;
}
else //否则认为是信号干扰导致
{
return 0; //认为没有按键按下
}
}
return 0; //如果没有按键按下返回零
}
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/bofangqi/article-356428-1.html
美国人的行动就是来挑战这种所谓的十二海里领海权
真的是做死啊