蓝桥杯-单片机(矩阵键盘)

文章详细介绍了矩阵键盘的工作原理,利用单片机检测按键的下降沿,通过改变列电位确定具体按键,同时提供了简单的C语言代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、矩阵键盘电路原理图

如果需要使用矩阵键盘的时候,需要将CON3的1和2进行短接。

在上一讲已经讲过按键的原理,在本文就不再赘述了,直接讲解一下矩阵键盘的工作原理:

        前文提到过,如果单片机需要检测到有一个按键是否被按下最好的解决方案是直接检测与该按键直接相连的单片机引脚上的电平变化,如果在除抖操作后检测到一个上升沿或者下降沿,则认为该按键被按下。在矩阵键盘中也采用相同的处理措施。

        15单片机的引脚都是采用的外接上拉电阻处理,所以在没有任何外设的影响下,单片机的引脚是处在高电平状态,所以,我们对于按键而言,只能采用捕获下降沿的方式(5V->0v)来判断按键是否被按下,而不可采用获取上升沿的方式来检验按键。

        通过观察原理图,我们可以发现,矩阵键盘是有四行,四列,共16个节点组成的按键矩阵,我们可以将其用坐标方式给每个按键一个新的表述:

仔细读矩阵键盘的原理图,(1,1)坐标下的按键是由P3^0(P3寄存器的第3位)和P4^4(P4寄存器的第4位)两个引脚控制的,那我们想要制造一个下降沿,可以让P44为低点位或者让P30为低huan电位,然后检测另一个引脚的电位变化,就可以得到我们想要的一个结果。

  如果前面设置都没问题,那么按照理论,按下(1,1)按键,P30的引脚上会出现一个下降沿,由此可以判断,(1,1)按键被按下。

        按照如此理论,我们只要去模仿(1,1)按键的例子,就能完成矩阵键盘的检测工作,仔细观察不难发现,我们其实并不需要去用一个for或者while的循环,循环16次来检测,我们可以从原理图中看出,每一列与4行相交都会有4个交点,我们只需呀将某一列/(某一行)的电位置为0V,其余列/(其余行)的电位置为5V,然后循环检测4行/(4列)上面的电位变化,就可以得到矩阵键盘上第一列中哪一个按键被按下,然后依此改变后面三列上的电位,就可以实现矩阵键盘的键位检测了。

二:代码部分

/*实现功能:根据矩阵键盘对应的数值,led显示其二进制数*/
#include <stc15f2k60s2.h>

sbit HC_A=P2^5;           
sbit HC_B=P2^6;           
sbit HC_C=P2^7;           

char result = 0;

void delay(unsigned int t)
{
	while(t--);
}

/*矩阵键盘部分*/
char button()
{
	P35 = 1;
	P36 = 1;
	P42 = 1;
	P44 = 0;	
	if(P30 == 0 && P44 == 0)
	{
		delay(200);
		while(P30 == 0);
		delay(200);
		return 0x01;
	}
	
	if(P31 == 0 && P44 == 0)
	{
		delay(200);
		while(P31 == 0 );
		delay(200);
		return 0x05;	
	}
	
	if(P32 == 0 && P44 == 0)
	{
		delay(200);
		while(P32 == 0);
		delay(200);
		return 0x09;	
	}
	
	if(P33 == 0 && P44 == 0)
	{
		delay(200);
		while(P33 == 0);
		delay(200);
		return 0x0D;	
	}
	P34 = 1;
	P35 = 1;
	P42 = 0;
	P44 = 1;
	if(P30 == 0 && P42 == 0)
	{
		delay(200);
		while(P30 == 0);
		delay(200);
		return 0x02;
	}
	
	if(P31 == 0 && P42 == 0)
	{
		delay(200);
		while(P31 == 0);
		delay(200);
		return 0x06;	
	}
	
	if(P32 == 0 && P42 == 0)
	{
		delay(200);
		while(P32 == 0);
		delay(200);
		return 0x0A;	
	}
	
	if(P33 == 0 && P42 == 0)
	{
		delay(200);
		while(P33 == 0);
		delay(200);
		return 0x0E;	
	}	

	P34 = 1;
	P35 = 0;
	P42 = 1;
	P44 = 1;
	if(P30 == 0 && P35 == 0)
	{
		delay(200);
		while(P30 == 0);
		delay(200);
		return 0x03;
	}
	
	if(P31 == 0 && P35 == 0)
	{
		delay(200);
		while(P31 == 0);
		delay(200);
		return 0x07;	
	}
	
	if(P32 == 0 && P35 == 0)
	{
		delay(200);
		while(P32 == 0);
		delay(200);
		return 0x0B;	
	}
	
	if(P33 == 0 && P35 == 0)
	{
		delay(200);
		while(P33 == 0);
		delay(200);
		return 0X0F;	
	}	

	P34 = 0;
	P35 = 1;
	P42 = 1;
	P44 = 1;
	if(P30 == 0 && P34 == 0)
	{
		delay(200);
		while(P30 == 0);
		delay(200);
		return 0x04;
	}
	
	if(P31 == 0 && P34 == 0)
	{
		delay(200);
		while(P31 == 0);
		delay(200);
		return 0x08;
	}
	
	if(P32 == 0 && P34 == 0)
	{
		delay(200);
		while(P32 == 0);
		delay(200);
		return 0x0C;		
	}
	
	if(P33 == 0 && P34 == 0)
	{
		delay(200);
		while(P33 == 0);
		delay(200);
		return 0xff;	
	}	
}
/*主函数*/
void main()
{
	HC_A = 0;
    HC_B = 0;
    HC_C = 1;         	
    P0 = 0xff;
	while(1)
	{
		result = button();
		P0 = ~result;
	}
}

<think>好的,我现在需要帮助用户查找关于蓝桥杯比赛中单片机矩阵键盘S16-19的示例代码及原理的资料。根据用户提供的引用内容,引用[1]和引用[2]都提到了矩阵键盘的相关内容,特别是引用[2]详细说明了矩阵键盘的连接方式和独立按键的处理方法。 首先,用户提到的S16-S19可能对应4x4矩阵键盘中的某几行或列,需要确认原理图连接。根据引用[2],当J5跳线帽接地时,S4-S7可以作为独立按键,接到P44则形成矩阵键盘。这说明矩阵键盘的行或列可能连接到特定的IO口,如P3或P4端口。 接下来,用户需要示例代码。矩阵键盘的扫描通常采用行扫描法或列扫描法。例如,设置行为输出,列为输入,逐行输出低电平,检测列的电平变化来确定按键位置。引用[2]中的代码片段展示了独立按键的处理,可以作为参考,但需要调整为矩阵键盘的逻辑。 此外,引用[1]提到矩阵按键的定义需要根据原理图进行,因此用户需要查阅具体的开发板原理图,确认S16-S19连接的IO口。例如,S16可能连接到P3.0,S17到P3.1,以此类推。代码中需要定义这些引脚,并编写扫描函数。 用户可能还关心消抖处理,这在矩阵键盘中尤为重要。引用[2]中的独立按键处理使用了延时消抖,同样适用于矩阵键盘的每个按键检测步骤。 最后,用户可能需要优化代码的方法,如使用状态机减少延时的影响,或者采用中断方式检测按键,这些在引用中没有提到,但可以作为扩展内容补充,提升回答的全面性。</think>### 蓝桥杯单片机矩阵键盘(S16-S19)原理与示例代码 #### 一、矩阵键盘原理 矩阵键盘通过行列交叉扫描实现多按键检测。以4x4矩阵为例,S16-S19可能对应某一行或列的引脚。根据引用[2],当跳线帽将矩阵键盘连接到P4口时,IO口需配置为 **推挽输出(行)** 和 **准双向输入(列)** 模式[^2]。 电路连接示例: - 行线:P30-P33(S16-S19) - 列线:P44-P47 扫描逻辑: 1. 逐行输出低电平 2. 检测列线电平变化 3. 通过行列组合确定按键位置 #### 二、示例代码(基于STC15系列单片机) ```c #include "stc15.h" #define KEY_PORT P3 // 假设行线连接P3低四位,列线连接P4高四位 unsigned char KeyScan() { unsigned char key_val = 0xFF; // 扫描第一行(P3.0) P3 = 0xFE; // 11111110 if ((P4 & 0xF0) != 0xF0) { delay_ms(10); // 消抖 switch(P4 & 0xF0) { case 0xE0: key_val = 0; break; // 第1列 case 0xD0: key_val = 1; break; // 第2列 case 0xB0: key_val = 2; break; // 第3列 case 0x70: key_val = 3; break; // 第4列 } while((P4 & 0xF0) != 0xF0); // 等待松开 } // 同理扫描其他三行(P3.1-P3.3) // ... return key_val + 16; // S16起始编号 } void delay_ms(unsigned int ms) { unsigned int i,j; for(i=ms;i>0;i--) for(j=845;j>0;j--); } ``` #### 三、关键点说明 1. **IO模式配置**: ```c P3M1 = 0x00; // 推挽输出模式 P3M0 = 0x0F; P4M1 = 0xF0; // 准双向输入模式 P4M0 = 0x00; ``` 2. **按键编号规则**: 行号×4 + 列号 + 起始编号,例如: $$S_{编号} = 行号×4 + 列号 + 16$$ 3. **消抖处理**:采用硬件消抖(电容)或软件延时(如示例中的`delay_ms(10)`)[^1]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值