学习记录——矩阵键盘

矩阵键盘


一、原理图分析

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/a7b06deaed234b5f8af4e35a7fc6afe5.png
红色为列,4x4=16个按键,4+4=8个IO口,4条I/O行线,4条I/O列线。


二、矩阵键盘扫描方式

矩阵键盘扫描的方式有两种: 1.行列扫描;2.逐行/逐列扫描

1.逐行/逐列扫描

寻找哪一按键按下
令第i行为低电平,其余行为高电平,逐个去看第i行的每一列是否出现0

#include <STC15F2K60S2.H>
unsigned char code SMG_duanma[18]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};//有小数点
void HC138(unsigned int n)
{
	switch(n)
	{
		case 4:
			P2=P2&0x1f|0x80;//LED
			break;
		case 5:
			P2=P2&0x1f|0xa0;//蜂鸣器和继电器
			break;
		case 6:
			P2=P2&0x1f|0xc0;//数码管位置
			break;
		case 7:
			P2=P2&0x1f|0xe0;//数码管数字
			break;
	}
}	
void Delay(unsigned int x)
{
	while(x--);
}
void SMG(unsigned char value)
{
	HC138(6);//打开数码管位置对应的573
	P0=0x01;
	HC138(7);//打开数码管数字对应的573
	P0=value;
}
void JuZhen()
{
	P30=0;
	P31=P32=P33=1;//令第i行为低电平,其余行为高电平,逐个去看第i行的每一列是否出现0
	P44=P42=P35=P34=1;
	if(P44==0)
	{
		Delay(100);
		if(P44==0)
		{
			SMG(SMG_duanma[0]);
			while(P44==0);
			
		}
	}
	else if(P42==0)
	{
		Delay(100);
		if(P42==0)
		{
			SMG(SMG_duanma[1]);
			while(P42==0);
			
		}
	}
	else if(P35==0)
	{
		Delay(100);
		if(P35==0)
		{
			SMG(SMG_duanma[2]);
			while(P35==0);
			
		}
	}
	else if(P34==0)
	{
		Delay(100);
		if(P34==0)
		{
			SMG(SMG_duanma[3]);
			while(P34==0);
			
		}
	}
	else
	{
		P31=0;
		P30=P32=P33=1;//令第i行为低电平,其余行为高电平,逐个去看第i行的每一列是否出现0
		P44=P42=P35=P34=1;
		if(P44==0)
		{
			Delay(100);
			if(P44==0)
			{
				SMG(SMG_duanma[4]);
				while(P44==0);
				
			}	
		}
		else if(P42==0)
		{
			Delay(100);
			if(P42==0)
			{
				SMG(SMG_duanma[5]);
				while(P42==0);
				
			}
		}
		else if(P35==0)
		{
			Delay(100);
			if(P35==0)
			{
				SMG(SMG_duanma[6]);
				while(P35==0);
				
			}
		}
		else if(P34==0)
		{
			Delay(100);
			if(P34==0)
			{
				SMG(SMG_duanma[7]);
				while(P34==0);
				
			}
		}
		else
		{
			P32=0;
			P30=P31=P33=1;//令第i行为低电平,其余行为高电平,逐个去看第i行的每一列是否出现0
			P44=P42=P35=P34=1;
			if(P44==0)
			{
				Delay(100);
				if(P44==0)
				{
					SMG(SMG_duanma[8]);
					while(P44==0);
					
				}	
			}
			else if(P42==0)
			{
				Delay(100);
				if(P42==0)
				{
					SMG(SMG_duanma[9]);
					while(P42==0);
					
				}
			}
			else if(P35==0)
			{
				Delay(100);
				if(P35==0)
				{
					SMG(SMG_duanma[10]);
					while(P35==0);
				
				}
			}
			else if(P34==0)
			{
				Delay(100);
				if(P34==0)
				{
					SMG(SMG_duanma[11]);
					while(P34==0);
				
				}
			}
			else
			{
				P33=0;
				P30=P32=P31=1;//令第i行为低电平,其余行为高电平,逐个去看第i行的每一列是否出现0
				P44=P42=P35=P34=1;
				if(P44==0)
				{
						Delay(100);
						if(P44==0)
						{
							SMG(SMG_duanma[12]);
							while(P44==0);
				
						}	
				}
				else if(P42==0)
				{
					Delay(100);
					if(P42==0)
					{
						SMG(SMG_duanma[13]);
						while(P42==0);
						
					}
				}
				else if(P35==0)
				{
					Delay(100);
					if(P35==0)
					{
						SMG(SMG_duanma[14]);
						while(P35==0);
						
					}
				}
				else if(P34==0)
				{
					Delay(100);
					if(P34==0)
					{
						SMG(SMG_duanma[15]);
						while(P34==0);
						
					}
				}
			}
		}
	}
}
void main()
{
	while(1)
	{
		JuZhen();
	}
}

2、更简便的写法

#include <STC15F2K60S2.H>
unsigned char code SMG_duanma[18]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};//有小数点
void HC138(unsigned int n)
{
	switch(n)
	{
		case 4:
			P2=P2&0x1f|0x80;//LED
			break;
		case 5:
			P2=P2&0x1f|0xa0;//蜂鸣器和继电器
			break;
		case 6:
			P2=P2&0x1f|0xc0;//数码管位置
			break;
		case 7:
			P2=P2&0x1f|0xe0;//数码管数字
			break;
	}
}	
/*声明变量*/
unsigned char Key_Val,Key_Down,Key_Up,Key_Old;
/*读取按键*/
unsigned char Key_Read()
{
	unsigned char temp=0;
	P30=0;P31=P32=P33=1;//令第1行为低电平,其余行为高电平,逐个去看第1行的每一列是否出现0
	if(P44==0)temp=1;
	if(P42==0)temp=2;
	if(P35==0)temp=3;
	if(P34==0)temp=4;
	P31=0;P30=P32=P33=1;//令第2行为低电平,其余行为高电平,逐个去看第2行的每一列是否出现0
	if(P44==0)temp=5;
	if(P42==0)temp=6;
	if(P35==0)temp=7;
	if(P34==0)temp=8;
	P32=0;P31=P30=P33=1;//令第3行为低电平,其余行为高电平,逐个去看第3行的每一列是否出现0
	if(P44==0)temp=9;
	if(P42==0)temp=10;
	if(P35==0)temp=11;
	if(P34==0)temp=12;
	P33=0;P31=P32=P30=1;//令第4行为低电平,其余行为高电平,逐个去看第4行的每一列是否出现0
	if(P44==0)temp=13;
	if(P42==0)temp=14;
	if(P35==0)temp=15;
	if(P34==0)temp=16;
	return temp;
}	
void SMG(unsigned char value)
{
	HC138(6);//打开数码管位置对应的573
	P0=0x01;
	HC138(7);//打开数码管数字对应的573
	P0=value;
}
void M()
{
	if(Key_Down==1)SMG(SMG_duanma[0]);
	if(Key_Down==2)SMG(SMG_duanma[1]);
	if(Key_Down==3)SMG(SMG_duanma[2]);
	if(Key_Down==4)SMG(SMG_duanma[3]);
	if(Key_Down==5)SMG(SMG_duanma[4]);
	if(Key_Down==6)SMG(SMG_duanma[5]);
	if(Key_Down==7)SMG(SMG_duanma[6]);
	if(Key_Down==8)SMG(SMG_duanma[7]);
	if(Key_Down==9)SMG(SMG_duanma[8]);
	if(Key_Down==10)SMG(SMG_duanma[9]);
	if(Key_Down==11)SMG(SMG_duanma[10]);
	if(Key_Down==12)SMG(SMG_duanma[11]);
	if(Key_Down==13)SMG(SMG_duanma[12]);
	if(Key_Down==14)SMG(SMG_duanma[13]);
	if(Key_Down==15)SMG(SMG_duanma[14]);
	if(Key_Down==16)SMG(SMG_duanma[15]);
	
}
void main()
{
	HC138(4);
	while(1)
	{
		Key_Val=Key_Read();
		Key_Down=Key_Val&(Key_Val^Key_Old);
		Key_Up=~Key_Val&(Key_Val^Key_Old);
		Key_Old=Key_Val;
		M();
	}
}
### 4x4矩阵键盘的行列扫描法及上拉电阻实现原理 #### 行列扫描法的工作机制 4x4矩阵键盘是一种常见的外部输入设备,其核心在于通过减少所需的I/O端口数量来优化硬件资源利用。具体来说,这种键盘由四行和四列表组成,总共可以提供16个按键位置[^1]。 在行列扫描法中,行线被配置为输出模式,而列线则设置为输入模式。为了检测哪个键被按下,首先将所有的行线置低电平(即发送逻辑0),然后逐行扫描并观察列线上是否有任何变化。如果某一行上的某个列线返回低电平,则说明该行与该列交叉处的按键已被按下[^2]。 以下是具体的扫描过程: - **初始化阶段**:设定行线为输出方向,并将其全部设为高电平;同时设定列线为输入方向。 - **逐行扫描**:每次仅有一条行线被拉低至接地状态(其余保持高电平)。随后读取所有列线的状态。 - **判定按下的键**:一旦发现某一列线变为低电平,则可确定当前处于激活状态的具体按键位置。 此方法能够有效降低GPIO引脚的需求量,从而节省微控制器接口资源[^3]。 #### 上拉/下拉电阻的作用及其应用 对于矩阵键盘而言,在实际电路设计过程中会涉及到使用到上拉或者下拉电阻的情况。这里以上拉电阻为例进行解释: 当未按下按钮时,默认情况下对应的输入针脚应该呈现已知稳定的电压等级以便于后续处理软件能正确解读信号含义。如果没有适当安排好这些条件的话可能会引起误判现象发生比如浮空输入等问题因此就需要引入额外元件帮助解决此类隐患—这就是为什么需要加装外接固定阻值大小合适的限流保护器件即常说的那种串联形式连接起来的小型金属膜类别的产品规格型号参数等等细节方面内容就不展开赘述了重点强调一点那就是它们主要起到稳定节点电势防止干扰杂波窜入影响正常功能运作效果达到预期目标要求标准范围内即可满足一般应用场景需求[^4]。 下面给出一段基于C语言编写用于演示如何操作上述提到过的那些概念的实际例子代码片段如下所示: ```c #include <reg51.h> sbit ROW1 = P1^0; sbit ROW2 = P1^1; sbit ROW3 = P1^2; sbit ROW4 = P1^3; sbit COL1 = P1^4; sbit COL2 = P1^5; sbit COL3 = P1^6; sbit COL4 = P1^7; unsigned char key_scan(void){ unsigned char i,j,key_value=0; for(i=0;i<4;i++){ switch(i){ case 0:ROW1=0;ROW2=1;ROW3=1;ROW4=1;break; case 1:ROW1=1;ROW2=0;ROW3=1;ROW4=1;break; case 2:ROW1=1;ROW2=1;ROW3=0;ROW4=1;break; case 3:ROW1=1;ROW2=1;ROW3=1;ROW4=0;break; } if(!COL1){key_value=i*4+1;while(!COL1);} // Debounce delay omitted here. else if(!COL2){key_value=i*4+2;while(!COL2);} else if(!COL3){key_value=i*4+3;while(!COL3);} else if(!COL4){key_value=i*4+4;while(!COL4);} if(key_value!=0)return key_value; } return 0; } ``` 这段程序实现了基本的功能框架结构用来完成整个项目开发周期内的初步验证测试目的足够胜任简单场合下的交互体验提升效率降低成本支出等方面优势明显值得推荐采用尝试一下看看效果怎么样再做进一步调整改进措施落实到位确保最终产品质量可靠耐用经得起时间考验赢得客户满意好评不断发展壮大企业规模实力增强竞争力水平提高经济效益增长速度加快步伐迈向成功彼岸共美好未来明天辉煌成就梦想成真!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值