
矩阵键盘应该是一种可以经常使用的设备。 4X4矩阵键盘只需要8个IO端口即可读取16位键。基本原理是扫描行和列。本文将带您详细学习矩阵键盘和代码编写的原理。
矩阵键盘的性质:
矩阵键盘的本质是使用8个io端口来控制和读取16个键,这可以减少io端口的使用。 4条I / O线用作行线,4条I / O线用作列线。组成键盘。在行线和列线的每个交叉点处,设置一个按钮。这种按钮中的按钮数是4 X 4。
这种确定性的键盘结构可以有效地提高微控制器系统中I / O端口的利用率。节省单片机的资源。其本质类似于独立密钥的本质。它是逐行扫描并逐列扫描,然后确定第一行和第一列中的哪个键,然后确定整体键值。收到我们使用的矩阵键盘。微控制器的P1端口可以通过读取P1端口的电平转换来读取矩阵键盘的值。具体原理图如下:

第一条线连接到p17,第二条线连接到p16,第三条线连接到p15,第四条线连接到p14
第一列连接到p13,第二列连接到p12,第三列连接到p11,第四列连接到p10
扫描矩阵键盘有两种方法:1.行和列扫描,2.行/列扫描
行和列扫描适用于连接到微控制器的8个连续IO端口的8个IO端口,然后可以执行行和列扫描。
逐行/列扫描适用于连接到任何IO端口的矩阵键盘,然后使用逐行和逐列扫描
接下来,我们将分别介绍这两种方法:
行和列扫描:
原理:
首先从端口P1的高四位(四行)输出高电平,然后从低四位(四列)输出低电平。假设按下了一个键,请从端口P1状态的高四位读取键盘。判断高四位的哪一行变为低电平,知道是哪一行,然后从P1端口的低四位(四列)输出高电平,并输出高四位(四行)低电平,从端口P1的低四位读取键盘状态。通过判断下面四列的哪一行已变低,您将知道它是哪一列。合并两个读取结果,以获取当前按钮的功能代码。通过以上方法,我们得到了16个按键的功能代码。

红色高电平,蓝色低电平

详细说明:
根据矩阵键盘的,如果矩阵键盘的8个IO端口连续连接到一个人P10-P17,则在不按任何键的情况下,将P1端口的P1 ^ 0和P13设置为P14和P17的高电平设置为低电平,即4行的IO端口设置为高电平,4列的IO端口设置为低电平。那就是P1 = 0x0f(0000 1111);
如果此时按任意键,则P1 ^ 0和P13之一将变为低电平。因此,P1的值不等于0x0f,并且按下按钮的行将变为低电平,这可以确定存在按下的按钮。
将对应的P1端口的值与0x0f(00001111)和&进行比较,可以得到高四位数字,并且前几行变为0
按位“与”&(双目运算符):仅当两个操作数均为1时,结果为1,否则为0。
例如:0&0 = 0; 0&1 = 0; 1&0 = 0; 1&1 = 1
即:两个同时为1,结果为1,否则为0
例如,按下的1x1的第一行和第一列
示例:
0000 1110 -------------按下1x1后的P1值
&0000 1111 ------------- 0x0f
----------
0000 1110 -------------最终结果,第一行为0
然后将0X0f分配给端口P1。将端口P1的P1 ^ 0和P13设置为低电平。将P14和P17设置为高电平,即将4个低IO端口设置为高电平,将4个列IO端口设置为高电平,然后读取低电平的4位,此时P1端口(1111 0000)
此时读取P1端口和0xf0(11110000)相位和&,您可以得到低四位数字,而前几列变为低电平
例如,我们按下1x1按钮,即第一行和第一列。这时,按下它后,您可以看到p 1. 0和p 1. 3都较低,并且Row = P1&0x0f;(行值)和Col = P1&0xf0; // column值相加了,你可以获得按下哪个按钮

1x1 :(一行一行)
行= P1&0x0f = 0000 1110
Col = P1&0xf0 = 1110 0000
Row + Col = 1110 1110 = 0xee
低级别0表示按下了相应的行和列。
您会看到下面的p 1. 0和p 1. 4变为低电平

2x2 :(两行两列)
行= P1&0x0f = 0000 1101
Col = P1&0xf0 = 1101 0000
Row + Col = 1101 1101 = 0xdd
3x4 :(三行四列)
行= P1&0x0f = 0000 1011
Col = P1&0xf0 = 0111 0000
Row + Col = 0111 1011 = 0x7b
通过这种方式,可以获得所有16个按钮的值。具体代码如下:

unsigned char keyscan(){
unsigned char key,Row,Col;
P1=0x0f;
if(P1!=0x0f){
delay(10);//去抖
if(P1!=0x0f){
Row=P1&0x0f;//确保端口值正确(行的值)
P1=0xf0;
Col=P1&0xf0;//列值
}
while((P1&0xf0)!=0xf0);//判断键是否抬起
}
switch(Row+Col){
case 0xee:key=0;break;
case 0xde:key=1;break;
case 0xbe:key=2;break;
case 0x7e:key=3;break;
case 0xed:key=4;break;
case 0xdd:key=5;break;
case 0xbd:key=6;break;
case 0x7d:key=7;break;
case 0xeb:key=8;break;
case 0xdb:key=9;break;
case 0xbb:key=10;break;
case 0x7b:key=11;break;
case 0xe7:key=12;break;
case 0xd7:key=13;break;
case 0xb7:key=14;break;
case 0x77:key=15;break;
}
return key;
}
运行效果图:

逐行/列扫描:
逐行扫描和逐列扫描的本质类似于行列扫描。本质是给某个行/某个列低级,而所有其他七个都为高级。这时,读取电平发生变化,有一个电平。当电平变低时,表示按下按钮并可以读取按钮数据。
例如,逐行扫描:
将第一行设置为低电平,其余的N-1行和N列为高电平,读取列线数据,列线为低电平表示该行有按键,例如为1行三列(1x3),则第三列的列线IO端口为低电平。将第二行设置为低电平,其余N-1行和N列为高电平,读取该列行数据,列线为低电平表示该行中有一个按钮被按下,以此类推,逐行扫描,根据行线和列线的级别,可以确定是否有按钮(n)根据键号跳转到相应的键处理程序。
以我们的P1端口为例:
首先,将P1 = 0xfe(1111 1110);分配给P1,此时P 1. 0为低电平,如果此时P 1. 1〜p 1. 7为高电平当按下按钮时有四列线,P 1. 4,P 1. 5,P 1. 6,P 1. 7且一列将变为低电平,因此,P1的值不等于设为0xfe,则可以判断为已按下按钮。
然后延迟一段时间以消除抖动,然后将0xfd(1111 1101)分配给P1,即P 1. 1为低电平,其他为高电平。 ,如果第1行上有P 1. P 1. 4,P 1. 5,P 1. 6,P 1. 7按下了按钮,则将显示低电平以确定按下哪个按钮;如果不是,则仅将0xfb(1111 1011)分配给P1,即P 1. 2为低电平,其他为高电平。使用相同的方法确定是否按下了按钮;··· ···依此类推,总共进行了四次检查。
例如,当在第一行中按下按钮时,P1的对应值为:
1X1(11101110 = 0xee)
1x2(11011110 = 0xde)
1X3(10111110 = 0xbe)
1X4(01111110 = 0x7e)
在第二行中按下按钮时对应的P1值:

2X1(11101101 = 0xed)
2x2(11011101 = 0xdd)
2X3(10111101 = 0xbd)
2X4(01111101 = 0x7d)
P1 ^ 2输出低电平,其他引脚输出高电平,即P1 = 0xfb,则当第三行中有按钮时,对应的P1值:
3X1(11101011 = 0xeb)
3x2(11011011 = 0xdb)
3X3(10111011 = 0xbb)
3X4(01111011 = 0x7b)
最后,第四行的相应值为:
4X1(11100111 = 0xe7)
4x2(11010111 = 0xd7)
4X3(10110111 = 0xb7)
4X4(01110111 = 0x77)
然后,我们终于可以获取代码:
/*****************************************************************************
** 函数名称:keyscan
** 功能描述:按键获取函数
******************************************************************************/
void keyscan(void)
{
P1=0xfe;
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10);
if(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xee: key=0;break;
case 0xde: key=1;break;
case 0xbe: key=2;break;
case 0x7e: key=3;break;
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
}
}
P1=0xfd;
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10);
if(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xed: key=4;break;
case 0xdd: key=5;break;
case 0xbd: key=6;break;
case 0x7d: key=7;break;
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
}
}
P1=0xfb;
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10);
if(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xeb: key=8;break;
case 0xdb: key=9;break;
case 0xbb: key=10;break;
case 0x7b: key=11;break;
}
beep=0;delay(50);beep=1;
while(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
}
}
P1=0xf7;
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10);
if(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xe7: key=12;break;
case 0xd7: key=13;break;
case 0xb7: key=14;break;
case 0x77: key=15;break;
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
}
}
}
运行效果图:


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/bofangqi/article-339198-1.html
狼真的来了
公司不行贿能够少纳税吗
我凡要出新歌啦