第十五届蓝桥杯单片机组备赛——独立键盘&矩阵键盘

一、按键原理

原理很简单,当我们没有按下SW2时,由于上拉电阻的作用,输入引脚的信号为高电平。因为按键的另一端接地,当按下按键后,引脚也就直接接地,输入单片机引脚的信号就为低电平。这时候,只要我们读取到IO口为低电平,那么按键就被按下了。

二、独立键盘&矩阵键盘

在这里插入图片描述

在比赛的板子上,独立键盘和矩阵键盘是合在一起的,通过跳线帽来选择是独立按键还是矩阵键盘(图中已经框起)。上图所示的是矩阵键盘,将跳线帽拔了换到另一边就是独立按键了。

2.1 独立按键

在这里插入图片描述

独立按键一段接着GND,说明只要按下按键引脚就输入低电平。这时候我们只需要读取按键所连接的IO口状态就可以判断按键是否被按下

2.2 矩阵键盘介绍

矩阵键盘中每个按键两端都接着单片机IO口,如果我们要使用某个按键就先设置按键一段IO为低电平,然后读取另一端IO口电平状态。矩阵键盘的原理就是IO口状态扫描,按照扫描的方式可以分为列扫描行扫描

2.2.1 列扫描

以下图为例,设置第二列的按键的一端为低电平(P42=0;),然后读取另一端的按键电平状态,如果读取到低电平就说明哪个按键被按下。例如读取P30口,如果P30==0,那么S11被按下。
在这里插入图片描述

2.2.2 行扫描

类似的,设置第一行的按键的一端为低电平(P30=0;),然后读取另一端的按键电平状态,如果读取到低电平就说明哪个按键被按下。例如读取P42口,如果P42==0,那么S11被按下。
在这里插入图片描述

2.3 矩阵键盘实现(阻塞方式,延时20ms,简单易懂)

2.3.1 代码实现(行扫描实现)

比赛的时候大概率不会用到这么多个按键,一般都是4个,所以说没有必要把所有按键判定都写进去,只需要写一部分就好了。

sbit R1=P3^0;
sbit R2=P3^1;
sbit R3=P3^2;
sbit R4=P3^3;

sbit C4=P3^4;
sbit C3=P3^5;
sbit C2=P4^2;
sbit C1=P4^4;

void delayForKeyboard()		//@12.000MHz,20ms
{
	unsigned char i, j;

	i = 234;
	j = 115;
	do
	{
		while (--j);
	} while (--i);
}

void keyBoard(){
	R1=0;R2=R3=R4=1;			// 设置第一行按键一段为低电平,其他行(hang)为高电平
	C1=C2=C3=C4=1;				// 将按键另一端设置为高电平(上拉)
	if(C1==0){					// 读取按键状态
		delayForKeyboard();		// 延时20ms,按键消抖
		if(C1==0){
			//......			// 在这里编写按下按键你想要完成的任务
		}
	}
	else if(C2==0){
		delayForKeyboard();
		if(C2==0){
			//......			// 在这里编写按下按键你想要完成的任务
		}
	}
	else if(C3==0){
		delayForKeyboard();
		if(C3==0){
			//......			// 在这里编写按下按键你想要完成的任务
		}
	}
	else if(C4==0){
		delayForKeyboard();
		if(C4==0){
			//......			// 在这里编写按下按键你想要完成的任务
		}
	}
	
	R2=0;R1=R3=R4=1;			// 设置第二行按键一段为低电平,其他行(hang)为高电平
	C1=C2=C3=C4=1;
	if(C1==0){
		delayForKeyboard();
		if(C1==0){
			//......			// 在这里编写按下按键你想要完成的任务
		}
	}
	else if(C2==0){
		delayForKeyboard();
		if(C2==0){
			//......			// 在这里编写按下按键你想要完成的任务
		}
	}
	else if(C3==0){
		delayForKeyboard();
		if(C3==0){
			//......			// 在这里编写按下按键你想要完成的任务
		}
	}
	else if(C4==0){
		delayForKeyboard();
		if(C4==0){
			//......			// 在这里编写按下按键你想要完成的任务
		}
	}
	
	R3=0;R1=R2=R4=1;			// 设置第三行按键一段为低电平,其他行(hang)为高电平
	C1=C2=C3=C4=1;
	if(C1==0){
		delayForKeyboard();
		if(C1==0){
			//......			// 在这里编写按下按键你想要完成的任务
		}
	}
	else if(C2==0){
		delayForKeyboard();
		if(C2==0){
			//......			// 在这里编写按下按键你想要完成的任务
		}
	}
	else if(C3==0){
		delayForKeyboard();
		if(C3==0){
			//......			// 在这里编写按下按键你想要完成的任务
		}
	}
	else if(C4==0){
		delayForKeyboard();
		if(C4==0){
			//......			// 在这里编写按下按键你想要完成的任务
		}
	}
	
	R4=0;R1=R3=R3=1;			// 设置第四行按键一段为低电平,其他行(hang)为高电平
	C1=C2=C3=C4=1;
	if(C1==0){
		delayForKeyboard();
		if(C1==0){
			//......			// 在这里编写按下按键你想要完成的任务
		}
	}
	else if(C2==0){
		delayForKeyboard();
		if(C2==0){
			//......			// 在这里编写按下按键你想要完成的任务
		}
	}
	else if(C3==0){
		delayForKeyboard();
		if(C3==0){
			//......			// 在这里编写按下按键你想要完成的任务
		}
	}
	else if(C4==0){
		delayForKeyboard();
		if(C4==0){
			//......			// 在这里编写按下按键你想要完成的任务
		}
	}
}

2.4 矩阵键盘(非阻塞式,定时器扫描,稍微有点难懂)

2.4.1 key_Scan()函数解释

  1. 该函数负责扫描矩阵键盘的按键状态,返回一个16位的无符号整数(u16),每一位代表一个按键是否被按下。
  2. 初始化变量temp为0,用来存储当前按键的状态,每一位对应一个按键。
  3. 设置P3端口的低四位为高电平,准备对这些行进行扫描。
  4. 通过一个嵌套循环,外循环遍历列,内循环遍历行。通过设置P44、P42、P35、P34这四个引脚的电平来选择一列,然后扫描对应列的四个行。
  5. 如果检测到某一行的电平是低电平,意味着对应的按键被按下了,于是把temp对应的位设置为1。

2.4.2 key_Proc()函数解释

  1. 这个函数负责处理按键的按下和释放事件。
  2. key_num变量用于存储当前扫描得到的按键状态。
  3. key_down用于记录这次扫描中按下的键。这是通过当前状态与前一次状态的异或运算(^)后与当前状态的按位与运算(&)得到的。
  4. key_up用于记录这次扫描中被释放的键。它通过对key_down取反(~)来得到。
  5. key_old用于记住上一次的键盘状态,以便下次扫描时可以比较变化。
  6. 有一个静态变量key_old,它用来存储上一次的按键状态,以便计算按下和释放的键。
  7. 函数中还有一个简单的节流逻辑:如果slow_down_for_key变量为真,则不更新按键状态,否则设置该变量为真。这是为了防止函数过于频繁地调用,应该在整个按键处理的逻辑外设置定时器,以保证10ms调用一次key_Proc()。
  8. 通过宏KEYDOWN_NUM(i)检测特定编号的按键是否按下。如果某个按键按下了,将执行相应的代码块。
#include "key.h"

//#define KEY_NUM(i)      
#define KEYDOWN_NUM(i)  key_down & (0x0001<<(i-4))
#define KEYUP_NUM(i)    key_up & (0x0001<<(i-4))

u16 key_Scan()
{
    u16 temp=0;     // 如果不初始化为0,会导致按键只能使用一次,后续无法使用    
    u8 col,row;
    P3=P3|0x0f;     // 拉高P3低四位,这一步似乎缺省也没事,为了保险起见所以加了这一句,所用和上面C1=C2=C3=C4=1一样。
    for(col=0;col<4;col++)
    {
        P44=(col!=0);
        P42=(col!=1);
        P35=(col!=2);
        P34=(col!=3);
        for(row=0;row<4;row++)
        {
            if(!(P3&(0x08>>row)))     // 千万不要错写成if(!P3&(0x08>>row))
            {
                temp|=( 1<<(col*4+row) );
            }
        }
    }
    return temp;
}


void key_Proc()
{
    u16 key_num,key_down,key_up;
    static u16 key_old=0;
    
    if(slow_down_for_key)   return;	// 定时器会每隔1ms给这个变量+1,加到10后就会自动置0,也就是让这个函数每隔10ms运行一次
    slow_down_for_key=1;
    
    key_num=key_Scan();
    key_down=key_num&(key_num^key_old);
    key_up=~key_down;
    key_old=key_num;

    if(KEYDOWN_NUM(4))
    {
        // S4被按下
    }
    if(KEYDOWN_NUM(5))
    {
		// S5被按下
    }
    if(KEYDOWN_NUM(8))
    {
		// S8被按下
    }
    if(KEYDOWN_NUM(9))
    {
    	// S9被按下
    }
}

三、矩阵键盘注意事项

3.1 为什么要设置C1=C2=C3=C4=1 或 P3|=0x0f;

为什么要设置C1=C2=C3=C4=1,原因在于51系列单片机的I/O端口设计为双向的,当没有指明IO的状态时,我们不知道IO口是处于高电平还是低电平,处于一种不稳定的状态,举个例子,如果不指定IO为高电平,那么这个时候由于之前的程序设置IO的状态不确定导致按键还没被按下IO就为低电平,这时候我们读取到的按键状态就是不正确的,所以需要我们指定它默认为高电平,然后才能通过读取IO判断按键是否按下。

3.2 按键消抖

按键抖动是由于按键的机械特性引起的,解决办法可以分为硬件消抖和软件消抖。
这个问题有很多人已经总结了,我就不再赘述。
【单片机】按键消抖及原理(硬件和软件方法详解)

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ct107d单片机是一种常见的单片机类型,广泛应用于各种电子设备中。蓝桥杯是中国著名的计算机及信息技术竞赛,矩阵键盘是一种常见的输入设备。下面我将介绍ct107d单片机如何与蓝桥杯矩阵键盘配合使用。 首先,ct107d单片机具有输入输出接口,可以与外部设备进行数据交互。蓝桥杯矩阵键盘通常采用矩阵排列的按钮形式,可以通过多个引脚与单片机相连。我们需要在单片机上配置对应的引脚,使其与蓝桥杯矩阵键盘的按键相对应。 然后,我们需要编写程序来读取输入的按键信息。在ct107d单片机上,可以使用GPIO口中断来实现按键的检测功能。当按键被按下时,引脚电平发生变化,触发GPIO口中断,单片机会执行相应的中断服务程序。我们可以在中断服务程序中读取按键的状态,并根据不同按键进行不同的处理。 在程序设计过程中,我们可以利用矩阵键盘的特性,将按键映射为矩阵的行和列。通过循环扫描的方式,逐一检测矩阵中的每个按键,并根据按键的状态进行相应的操作。例如,当按键按下时,可以执行一些特定的功能,如发送数据、改变显示内容等。 总结起来,ct107d单片机蓝桥杯矩阵键盘的配合使用,需要在单片机上配置引脚连接,编写相应的程序来读取按键信息,并根据按键状态进行相应的处理。这样,就能够实现方便的按键输入功能,在蓝桥杯竞赛及其他实际应用中发挥作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值