【单片机基础】按键与矩阵键盘识别

本文介绍了单片机按键的硬件连接及识别方法,重点讲解了按键消抖的电容与软件两种策略,并详细阐述了矩形矩阵键盘的工作原理和扫描过程。通过实例演示,学习者可掌握如何在实际项目中处理按键抖动和矩阵键盘的编程操作。

1、单片机按键识别方法

单片机硬件按键有接电源和接地两种接发,我们通过程序判断当前引脚电平的高低来判断按键按下/放开。

程序略…

2、按键消抖的方法

我们知道机械按键在按下和弹起时,会因为产生抖动,出现高低电平快速变化,因此我们必须进行消抖处理。
请添加图片描述
常用的消抖方法有两种:电容消抖和软件消抖
代码例程:

if(switch_1 == 0)//判断switch_1按键按下时
{
	Delay_ms(30);//延时消抖
	if(switch_1 == 0)//再次判断switch_1按键按下
	{
		while(!switch_1);//松手检测
		//请将按键功能写在下面
		
	}
}

电容消抖:利用电容的放电延时,采用并联电容法,使两端电压平缓变化,直至电容充放电到达一定电压阀值时,单片机才能读取到电平变化。
请添加图片描述
软件消抖:写一段延时毫秒级延时函数,在按键按下后延时一段时间再次判断按键电平。但是软件消抖是以CPU资源为代价,会降低程序的执行效率,所以我们在做大型项目开发时,要尽量避免使用延时消抖。

3、矩形键盘原理

请添加图片描述
矩阵键盘一共有4行和4列一共16个按键组成,确定矩阵键盘上哪一个按键被按下可以采用列扫描和行扫描。

列扫描时先把接在列上面的IO拉高,接在行的所以IO置低,当其中有一列任何一个按键按下,那么整条都会被拉低。


我写好了一段矩阵键盘例程,封装成一个函数库。日后直接调用和工程参考,例程主要功能是当矩阵键盘任何值按下时,向串口发送当前按下矩阵键盘的值,例程带有矩阵键盘松手检测功能。

#include <reg52.h>
#include <intrins.h>

#define uint unsigned int
#define uchar unsigned char

/*常量宏定义*/	
#define RECTANGUAR_KRYBOARD_IO P3//矩阵键盘IO口


//串口初始化,波特率9600
void InitUART(void)
{
    TMOD = 0x20;//设置定时器1,工作方式2,8位自动重载
    SCON = 0x40;//设置串口工作方式1
    TH1 = 0xFD;//波特率设置为9600
    TL1 = TH1;
    PCON = 0x00;//波特率不加倍
    EA = 1;//开总中断
    ES = 1;//允许串联1中断
    TR1 = 1;//启动定时器T1
}

//1ms延时函数
void Delay1ms(void)		//@11.0592MHz
{
	unsigned char i, j;

	_nop_();
	i = 2;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}

//毫秒延时函数
void delay_ms(uint time)
{
	uint i;
	for(i=0; i<time; i++)
	{
		Delay1ms();
	}
}

//向串口发送一个字符
void putchar(char ch)
{
	SBUF = ch;
	while(!TI);TI = 0;
}


//向串口发送一段字符串
void prints(char *s)
{
	while(*s != '\0')//发送字符串,直到遇到0才结束
	{
		SBUF = *s++;
		while(!TI);
		TI = 0;
	}
}

/******************************************************
函数名称:RectanguarKeyboard_Scanning(void)
函数输入:无
函数返回:unsigned int
函数说明:4*4矩阵键盘与独立键盘扫描
		  调用此函数,需添加RECTANGUAR_KRYBOARD_IO宏定义
*******************************************************/
uint RectanguarKeyboard_Scanning(void)
{
	uint num;
	//4*4矩阵键盘扫描
	RECTANGUAR_KRYBOARD_IO = 0xf0;//列扫描
	if(RECTANGUAR_KRYBOARD_IO != 0xf0)//判断按键是否按下
	{
		delay_ms(5);//软件消抖
		if(RECTANGUAR_KRYBOARD_IO != 0xf0)
		{
			switch(RECTANGUAR_KRYBOARD_IO)//判断那一列被按下
			{
				case 0xe0:	num=1; break;//第一列被按下
				case 0xd0:	num=2; break;//第二列被按下
				case 0xb0:	num=3; break;//第三列被按下
				case 0x70:	num=4; break;//第四列被按下
			}
			P3 = 0x0f;//行扫描
			switch(RECTANGUAR_KRYBOARD_IO)
			{
				
				case 0x0e:  while(RECTANGUAR_KRYBOARD_IO != 0x0f); return num;					//第一行被按下	
				case 0x0d:  while(RECTANGUAR_KRYBOARD_IO != 0x0f); num = num + 4; return num;	//第二行被按下
				case 0x0b:  while(RECTANGUAR_KRYBOARD_IO != 0x0f); num = num + 8; return num;	//第三行被按下
				case 0x07:  while(RECTANGUAR_KRYBOARD_IO != 0x0f); num = num + 12; return num;	//第四行被按下
			}
		}
	}
	return 0;
}

void main(void)
{
	char str[2];
	uchar temp = 0;
	
	InitUART();//初始化串口
	
	while(1)
	{
		temp = RectanguarKeyboard_Scanning();
		if(temp != 0)
		{
			if(temp < 10 && temp != 0)
			{
				temp = temp + '0';
				putchar(temp);
			}
			else if(temp >= 10 && temp != 0)
			{
				str[0] = temp / 10 + '0';
				str[1] = temp % 10 + '0';
				
				prints(str);
			}
			
			temp = 0;
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小明n.n

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值