一、接线(4×4)
将16个键盘排成4行4列,第一行将每个按键的一端连接在一起构成行线,第一列将每个按键的另一端连接在一起构成列线,所以共有4行4列8根线,连接到单片机的GPIO口。
二、原理
总体来说检测该键对应IO口是否为低电平。
1、检测时,先将一行设为低电平,其余几行为高电平。
2、然后立即轮流检测一次各列是否为低电平,若检测到某一列为低电平,可以确定是某行某列的按键,设置此按键的键值。
3、用同样的方法轮流设置各行为低电平,再轮流检测各列是否为低电平,这样就可以检测完所有的按键,扫描所有的键值。
4、也可以设置列为低电平再检测各行。
三、例子
通过数码管,按键显示对应的键值,按键行接P3.0-P3.3,按键列接P3.4-P3.7,代码如下:
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
void Delay_ms(uint y);
void Display(uchar x);
void MatrixKEYDect();
void Init();
sbit WE1 = P2^4; //数码管十位位选
sbit WE2 = P2^5; //数码管个位位选
//8段共阴极数码管
uchar code SEG[] = {
//0 1 2 3 4
0x3f, 0x06, 0x5b, 0x4f, 0x66,
//5 6 7 8 9
0x6d, 0x7d, 0x07, 0x7f, 0x6f};
uint KEYNum; //按键显示的数字
void main()
{
Init(); //初始化
while(1)
{
MatrixKEYDect(); //扫描查询按键
Display(KEYNum); //根据键值显示
}
}
//延时函数,单位1ms
void Delay_ms(uint y)
{
uint i,j;
for(i=y; i>0; i--)
{
for(j=110; j>0; j--);
}
}
//初始化函数
void Init()
{
WE1 = 0; //初始关闭数码管
WE2 = 0;
P2 = 0x0f; //因为开发板有4个数码管,此实验只使用两个,初始关闭4个数码管
P3 = 0xff; //拉高按键电平,保证初始值正确
}
//显示函数
void Display(uchar x)
{
uchar ge,shi;
ge = x % 10;
shi = x / 10;
WE1 = 0;
WE2 = 1;
P0 = SEG[ge];
Delay_ms(5);
WE1 = 1;
WE2 = 0;
P0 = SEG[shi];
Delay_ms(5);
}
/*
按键查询
3.4 3.5 3.6 3.7
3.0 0 1 2 3
3.1 4 5 6 7
3.2 8 9 A B
3.3 C D E F
*/
void MatrixKEYDect()
{
uchar temp, i;
for(i=0; i<4; i++) //每将一行拉低置0,然后再去查询每一列,若为低电平,则有按键按下,一共4行
{
P3 = ~(0x01 << i); //第一行:0xfe;第二行:0xfd;第三行:0xfb;第四行:0xf7
temp = P3; //拉低行值后,使用临时变量读取P3 GPIO数值
temp = temp & 0xf0; //高4位为列,与0xf0相与,若按键没被按下,则结果还是0xf0;若按键被按下则不等
if(temp != 0xf0)
{
Delay_ms(10); //延时10ms,消抖,再重新检测一次
temp = P3;
temp = temp & 0xf0;
if(temp != 0xf0)
{
temp = P3;
switch(temp) //查询键值
{
case 0xee:
KEYNum = 0; //第1行第1列
break;
case 0xde:
KEYNum = 1; //第1行第2列
break;
case 0xbe:
KEYNum = 2; //第1行第3列
break;
case 0x7e:
KEYNum = 3; //第1行第4列
break;
case 0xed:
KEYNum = 4; //第2行第1列
break;
case 0xdd:
KEYNum = 5; //第2行第2列
break;
case 0xbd:
KEYNum = 6; //第2行第3列
break;
case 0x7d:
KEYNum = 7; //第2行第4列
break;
case 0xeb:
KEYNum = 8; //第3行第1列
break;
case 0xdb:
KEYNum = 9; //第3行第2列
break;
case 0xbb:
KEYNum = 10; //第3行第3列
break;
case 0x7b:
KEYNum = 11; //第3行第4列
break;
case 0xe7:
KEYNum = 12; //第4行第1列
break;
case 0xd7:
KEYNum = 13; //第4行第2列
break;
case 0xb7:
KEYNum = 14; //第4行第3列
break;
case 0x77:
KEYNum = 15; //第4行第4列
break;
default:
break;
}
}
while(temp != 0xf0) //等待按键释放
{
temp = P3;
temp = temp & 0xf0;
}
}
}
}
版权声明:本文为weixin_44064291原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。