一、接线(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 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_44064291/article/details/127721818