51单片机独立按键和矩阵按键实现

这里写目录标题

独立按键实验

按键是一种电子开关,使用时轻轻按开关按钮就可使开关接通,当松开手时,
开关断开。我们开发板上使用的按键及内部简易图如下图所示
在这里插入图片描述

管脚与管脚之间(注意是距离)距离长的是导通状态,短的是接通状态。
通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,电压信号
如下图所示:
在这里插入图片描述

如图所示,按键闭合式不会立刻稳定的接通,断开时也不会一下子断开,会伴随一些抖动。抖动的时间长短有按键特性决定,一般为5Ms到10ms.按键抖动会引起按键被误读多次。为了确保 CPU 对按键的一次闭合仅作一次处理,必须进行消抖

  • 消抖
    消抖可分为硬件消抖和软件消抖。为了使电路更加简单,通常采用软件消抖。
    一般来说一个简单的按键消抖就是先读取按键的状态, 如果得到按键按下之后, 延时 10ms, 再次读取按键的状态,如果按键还是按下状态,那么说明按键已经按下。 其中延时 10ms 就是软件消抖处理。
    消抖过程(软件)
    1,先设置 IO 口为高电平(由于开发板 IO 都有上拉电阻,所以默认 IO 为高电平)。
    2,读取 IO 口电平确认是否有按键按下。
    3,如有 IO 电平为低电平后,延时几个毫秒。
    4,再读取该 IO 电平,如果任然为低电平,说明对应按键按下。
    5,执行相应按键的程序。
  • 键盘
    键盘分为编码键盘和非编码键盘。键盘上闭合键的识别由专用的硬件编码器实现,并产生键编码号或键值的称为编码键盘,如计算机键盘。而靠软件编程来识别的键盘称为非编码键盘,在单片机组成的各种系统中,用的较多的是非编码键盘。非编码键盘又分为独立键盘和行列式键盘(常说的矩阵键盘)。独立按键用的就是独立键盘。
  • 实现原理
    原理图:
    在这里插入图片描述

独立按键电路构成是由各个按键的一个管脚连接在一起接地,按键其他引脚分别接到单片机 IO 口。
单片机的 IO 口既可作为输出也可作为输入使用,当检测按键时用的是它的输入功能,独立按键的一端接地,另一端与单片机的某个 I/O 口相连,开始时先给该 IO 口赋一高电平,然后让单片机不断地检测该 I/O 口是否变为低电平,当按键闭合时,即相当于该 I/O 口通过按键与地相连,变成低电平,程序一旦检测到 I/O 口变为低电平则说明按键被按下,然后执行相应的指令。
在这里插入图片描述

由图可以看出,单片机的管脚(p1,p3,等管脚)都接有上拉电阻,上拉电阻接高电平。因此我们在消抖检测时,若按键以已经按下,则管脚接地,变为低电平,若管脚为低电平,则说明按键已经按下,执行LED灯点亮的步骤。

  • 代码实现
#include <reg52.h>
#include <intrins.h>
typedef unsigned char u8; //重定义全局字符型变量
typedef unsigned int u16; //重定义全局整型变量
sbit LED=P2^0 ;  //LED接P2口
sbit K1=P3^1; //按键k1接p3口,也可以是其他管脚

/*延时函数*/
void dealy(u16 i)
{
while(i--);
}

/*独立按键执行函数
*/
void KeyProcess()
{  
   if(K1==0){
     dealy(1000);
	 //一个int型的所占的时间大约为10微妙,所以乘1000大约为10ms.
	 if(K1==0){  //消抖后仍为低电平,则执行点亮进程
	  LED=~LED;    //为了让LED产生明暗变化
	 }
	 while(!K1);  //判断按键是否松开,假如松开,则K1为真,加!为假,则循环结束跳出循环
   }
   
}

void main()
{ 
  LED=0;  //初始时灯位熄灭状态(LED原理),
  while(1)
  {
  	KeyProcess();
  }	 
}
矩阵按键实验
  • 前面我们讲到独立按键,接下来我们引入独立按键。为什么引入矩阵按键?
    独立键盘与单片机连接时,每一个按键都需要单片机的一个 I/O 口,若某单片机系统需较多按键,如果用独立按键便会占用过多的 I/O 口资源。单片机系统中 I/O 口资源往往比较宝贵,多个按键时为了减少 I/O 口引脚。
  • 4 * 4键盘的工作原理
    矩阵按键原理图
    在这里插入图片描述

开发板上将 16 个按
键排成 4 行 4 列,第一行将每个按键的一端连接在一起构成行线,第一列将每
个按键的另一端连接在一起构成列线,这样便一共有 4 行 4 列共 8 根线,我们将
这 8 根线连接到单片机的 8 个 I/O 口上,通过程序扫描键盘就可检测 16 个
键。

  • 矩阵按键的消抖
    1.检查按键是否按下
    在这里插入图片描述

由原理图可知,独立按键和矩阵按键是有所不同的。独立按键的各个按键一端接引脚,一端并联在一起接地。所以检测按键是否按下只需要看单片机的管脚是否为低电平即可。而矩阵按键,他们的两端分别并联在一起,
每一行(共4行)并联在一起接高位管脚上(7-4),每一列(共4列)并联在一起接到低位管脚上(3~0)。
所以检测方法有所不同。
一般情况下有两种方法。
方法一:
逐行扫描:我们可以通过高四位轮流输出低电平来对矩阵键盘进行逐行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一位为0来判断是哪一个按键被按下。逐行扫描的时间是非常快的,肉眼难以观察。
举个例子,假设此时p7管脚为低电平,那么第一行按键的一段都为低电平,另一端分别连接低4位的管脚,只有当某一个开关按下,低4位的管脚与其中一个低电平的管脚连接变为低电平,所以只要查看低4位那个管脚为低电平就可以确定那个按键以按下。其他三行同理,每一行依次不断进行。
方法二:
行列扫描:我们可以通过高四位全部输出低电平,低四位输出高电平。当接收到的数据,低四位不全为高电平时,说明有按键按下,然后通过接收的数据值,判断是哪一列有按键按下,然后再反过来,高四位输出高电平,低四位输出低电平,然后根据接收到的高四位的值判断是那一行有按键按下,这样就能够确定是哪一个按键按下了。相当于第一次确定列,第二次确定行,行列交叉形成点,这个点就是我们要找的已经闭合的按键。

  • 静态数码管显示按键
    在这里插入图片描述

如图,每一个按键可用一个键值来代替,让对应的键值号来作为静态数码管的段选,从而实现按下按键显示数字的效果。

  • 代码实现
    采用第二种行列扫描的检测方法
#include <reg52.h>			 //此文件中定义了单片机的一些特殊功能寄存器

typedef unsigned int u16;	  //对数据类型进行声明定义
typedef unsigned char u8;

#define GPIO_DIG P0	   //宏定义p0口(静态显示数码管对应的管脚)
#define GPIO_KEY P1	  //矩阵按键对应管脚
u8 KeyValue;	//用来存放读取到的键值
u8 code smgduan[17]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
					0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//显示0~F的值
					
/*延时·函数*/
void delay(u16 i)
{
	while(i--);	
}

/*检测按键是否按下,消抖,读取键值*/
void KeyDown(void)
{
	char a=0;
	GPIO_KEY=0x0f;	  
	//0x0f十六进制转化为为二进制为0000 1111,即矩阵按键的八个管脚,高位为低电平(0),低位为高电平(1)
	if(GPIO_KEY!=0x0f)//读取按键是否按下
	{
		delay(1000);//延时10ms进行消抖
		if(GPIO_KEY!=0x0f)//再次检测键盘是否按下
		{	
			/*对列进行测试(高位低电平,低位高电平)*/
			GPIO_KEY=0X0F;
			switch(GPIO_KEY)
			{
				case(0X07):	KeyValue=0;break; //对应管脚高低电平0000 0111,第0列
				case(0X0b):	KeyValue=1;break; //对应管脚高低电平0000 1011,第1列
				case(0X0d): KeyValue=2;break; //对应管脚高低电平0000 1101,第2列
				case(0X0e):	KeyValue=3;break;//对应管脚高低电平0000 1110,第3列
			}
			/*对行进行测试(低位高电平,高位低电平)*/
			GPIO_KEY=0XF0;
			switch(GPIO_KEY)
			{	 /*上一行对应的列号加上相应有规律的字号就等于按键号,可由原理图查看*/
				case(0X70):	KeyValue=KeyValue;break; //对应管脚高低电平0111 0000,第0行
				case(0Xb0):	KeyValue=KeyValue+4;break; //对应管脚高低电平1011 0000,第1行
				case(0Xd0): KeyValue=KeyValue+8;break;//对应管脚高低电平1101 0000,第2行
				case(0Xe0):	KeyValue=KeyValue+12;break;	//对应管脚高低电平1110 0000,第0行
			}
			
		}
	}
	while((a<50)&&(GPIO_KEY!=0xf0))
    //检测按键松手检测(只有当按键松开时矩阵连接的管脚高位和低位才会互换继续检测行。否则进行循环延迟)
	{
		delay(100);
		a++;
	}
}

/*主函数*/
void main()
{	

	while(1)
	{	
		KeyDown();		   //按键判断函数
		GPIO_DIG=~smgduan[KeyValue];	  //
	}		
}
  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值