按键通常指的是电子设备上的一种输入装置,用于在按下时发送信号,以便设备执行相应的操作。按键可以分为独立按键和矩阵按键两种类型。
先来简单说一下独立按键,独立按键是指每一个按键都独立连接到单片机或者其他处理器的一个引脚上,每个按键都有自己的引脚,通过检测这个引脚的电平变化来确定按键是否被按下,常用于需要少量按键且按键数量有限的场合,比如遥控器、小型仪器等。
这里放几种按键的实物图,它们的区别在于封装,形状等。
接下来简单说一下矩阵按键,矩阵按键则是独立按键的组合,是指将多个按键组织成一个矩阵的形式连接到单片机或者其他处理器的引脚上,通过在行和列之间扫描判断,可以确定按键按下的位置。矩阵按键节省了引脚资源,使得可以通过少量引脚连接大量按键。常用于需要大量按键且按键数量较多的场合,比如键盘、数字输入器等。
既然谈到了按键,那也简单说一下按键的抖动以及如何做消抖。
按键的抖动是由于按键开关的机械弹性特性,在按键按下或松开时,触点闭合或断开的瞬间会产生接触不稳定,导致输出电平不稳定,从而出现键抖动现象。这种抖动可能会导致CPU对一次按键操作进行多次处理,产生错误的操作,因此需要消除抖动的不良后果。
消抖的方式主要有两种:硬件消抖和软件消抖。
硬件消抖主要是用RC滤波去抖电路,RC滤波电路由电阻(R)和电容(C)组成,在按键按下或释放的过程中,由于电容的充放电过程,输入信号会经过平滑处理,抑制抖动信号,从而使得输出信号相对稳定。
但是要注意:电容和电阻的数值会影响RC滤波电路的响应时间和抖动抑制效果。通常情况下,选择较大的电容和较大的电阻可以实现更好的抖动抑制效果,但同时会增加响应时间。因此需要在稳定性和响应速度之间进行权衡。
软件消抖主要包括延时消抖和状态检测消抖。延时消抖顾名思义就是在检测到按键按下后,通过延时一段时间来等待按键的抖动过程结束,然后再进行状态的确认。这种方法简单易行,但需要根据具体情况设置合适的延时时间。而状态检测消抖主要是针对在检测到按键按下或释放时,通过连续检测一定时间内按键的状态,只有当按键的状态保持一段时间后才确认按键操作有效。这种方法相对较精确,能够有效地避免误判。
独立按键的仿真图相对简单,就是通过一个按键按下来将一个和指示灯的状态取反。
Individual key
/**************************************************************************************
* 独立按键实验 *
实现现象:下载程序后按下K1按键可以对D1小灯状态取反。
注意事项:无
***************************************************************************************/
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
sbit k1=P3^5; //定义P31口是k1
sbit led=P3^1; //定义P20口是led
/*******************************************************************************
* 函 数 名 : delay
* 函数功能 : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
while(i--);
}
/*******************************************************************************
* 函 数 名 : keypros
* 函数功能 : 按键处理函数,判断按键K1是否按下
*******************************************************************************/
void keypros()
{
if(k1==0) //检测按键K1是否按下
{
delay(1000); //消除抖动 一般大约10ms
if(k1==0) //再次判断按键是否按下
{
led=~led; //led状态取反
}
while(!k1); //检测按键是否松开
}
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
while(1)
{
keypros(); //按键处理函数
}
}
如下的仿真图初始共阳数码管显示0,有一个4*4的矩阵按键,每一个按键按下,数码管都会显示1个数字,总共显示0~F。
Matrix keying
以下代码实现了一个基本的矩阵按键扫描功能,并在数码管上显示按下的键值对应的数字。
在检测按键时,首先将行设置为低电平,列设置为高电平,然后检测是否有按键按下;接着再次检测按键,但这次将列设置为低电平,行设置为高电平,以此来确定按下的具体按键。在主循环中不断地检测按键,并根据按键的值在数码管上显示对应的数字。
/**************************************************************************************
* 矩阵按键实验 *
实现现象:下载程序后数码管显示0,按下矩阵按键上的按键显示对应的数字
注意事项:
***************************************************************************************/
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
#define GPIO_DIG P0
#define GPIO_KEY P3
u8 KeyValue; //用来存放读取到的键值
u8 code smgduan_anode[17] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82,
0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E}; // 共阳数码管显示0~F的值
/*******************************************************************************
* 函 数 名 : delay
* 函数功能 : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
while(i--);
}
/*******************************************************************************
* 函 数 名 : KeyDown
* 函数功能 : 检测有按键按下并读取键值
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void KeyDown(void)
{
char a=0;
GPIO_KEY=0x0f;
if(GPIO_KEY!=0x0f)//读取按键是否按下
{
delay(1000);//延时10ms进行消抖
if(GPIO_KEY!=0x0f)//再次检测键盘是否按下
{
//测试列
GPIO_KEY=0X0F;
switch(GPIO_KEY)
{
case(0X07): KeyValue=0;break;
case(0X0b): KeyValue=1;break;
case(0X0d): KeyValue=2;break;
case(0X0e): KeyValue=3;break;
}
//测试行
GPIO_KEY=0XF0;
switch(GPIO_KEY)
{
case(0X70): KeyValue=KeyValue;break;
case(0Xb0): KeyValue=KeyValue+4;break;
case(0Xd0): KeyValue=KeyValue+8;break;
case(0Xe0): KeyValue=KeyValue+12;break;
}
while((a<50)&&(GPIO_KEY!=0xf0)) //检测按键松手检测
{
delay(1000);
a++;
}
}
}
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
while(1)
{
KeyDown();//按键判断函数
GPIO_DIG=smgduan_anode[KeyValue];
}
}
今天主要讲了基于51单片机的矩阵按键扫描的proteus仿真。
感谢你的观看!