51单片机——独立按键、矩阵按键多种方案1.1

1、优化了《51单片机——独立按键、矩阵按键多种方案1.0》的代码。

2、添加了矩阵按键逐行扫描法KEY16_1、KEY16_2

#ifndef __KEY_H__
#define __KEY_H__

#include "delay.h"

//按键占用P3口
extern unsigned char key(void);//返回2则按键2被按下,其他按键同理,本函数只循环扫描一次
extern unsigned char key2345(void); //函数返回值为2、3、4、5分别对应按键2、按键3、按键4、按键5,本函数只循环一次
extern unsigned char key16(void);//判断16个按键中哪个被按下,本函数只循环一次   炒while松手检测忘记加;号了

#endif // !__KEY_H__
//独立按键 S2		S3		 S4			S5
//分别对应 P30/TX	P31/RX	 P32/INTO	P33/INT1
#include"key.h"
#include <reg52.h>

#define key_all P3
sbit key_S2 = P3^0;
sbit key_S3 = P3^1;
sbit key_S4 = P3^2;
sbit key_S5 = P3^3;

//独立按键,函数返回值为2、3、4、5分别对应按键2、按键3、按键4、按键5
unsigned char key(void)//返回2则按键2被按下,其他按键同理,本函数只循环扫描一次
{
	key_S2 = 1;
	key_S3 = 1;
	key_S4 = 1;
	key_S5 = 1;

	if (!key_S2)
	{
		delay_ms(10);//防抖滤波延迟
		if (!key_S2)
		{
			while (!key_S2);//按键松手检测
			return	2;
		}
	}
	if (!key_S3)
	{
		delay_ms(10);//防抖滤波延迟
		if (!key_S3)
		{
			while (!key_S3);//按键松手检测
			return 3;
		}
	}
	if (!key_S4)
	{
		delay_ms(10);//防抖滤波延迟
		if (!key_S4)
		{
			while (!key_S4);//按键松手检测
			return 4;
		}
	}
	if (!key_S5)
	{
		delay_ms(10);//防抖滤波延迟
		if (!key_S5)
		{
			while (!key_S5);//按键松手检测
			return 5;
		}
	}
	return 0;//没有按键按下时,返回0个函数
}

//独立按键使用switch语句
unsigned char key2345(void) //函数返回值为2、3、4、5分别对应按键2、按键3、按键4、按键5,本函数只循环一次
{
	if ((key_all&0x0f) != 0x0f)	//&运算符没有!=高,故需要加()括号
	{
		delay_ms(10);
		if ((key_all & 0x0f) != 0x0f)//忘记加{号了  哎
		{
			switch (key_all & 0x0f)
			{
			case 0x0e:while ((key_all & 0x0f) != 0x0f);return 2;	//while在这里进行松手检测  炒while松手检测忘记加;号了
			case 0x0d:while ((key_all & 0x0f) != 0x0f);return 3;	//while在这里进行松手检测
			case 0x0b:while ((key_all & 0x0f) != 0x0f);return 4;	//while在这里进行松手检测
			case 0x07:while ((key_all & 0x0f) != 0x0f);return 5;	//while在这里进行松手检测
			}
		}
	}
	return 0;//没有按键按下时返回0
}

//矩阵按键真值表4行*4列计算器使用
static unsigned char code key_true1[4][4] = { '+','-','*','/',
								   7,  8,  9,  0,
								   4,  5,  6,  0,
								   1,  2,  3, '=' };
//矩阵按键真值表4行*4列判断是哪个按键被按下
static unsigned char code key_true2[4][4] = { 
									1,	2,	3,	4,
									5,  6,  7,  8,
									9,  10,	11,	12,
									13, 14,	15,	16
													};

//矩阵按键,行列互换法
unsigned char key16(void)//判断16个按键中哪个被按下,本函数只循环一次  若没有按键按下此函数会自动返回0
{
	unsigned char x = 0;
	unsigned char y = 0;
	key_all = 0x0f;
	if(key_all!=0x0f)
	{
		delay_ms(10);
		if (key_all!=0x0f)
		{
			switch (key_all)
			{
			case 0x0e:x = 0;break;
			case 0x0d:x = 1;break;
			case 0x0b:x = 2;break;
			case 0x07:x = 3;break;
			}
			key_all = 0xf0;
			switch (key_all)
			{
			case 0xe0:y = 0;break;
			case 0xd0:y = 1;break;
			case 0xb0:y = 2;break;
			case 0x70:y = 3;break;
			}
		while (key_all != 0xf0);//松手检测,检测上次赋值0xf0
		return key_true2[x][y]; //在这里函数返回1/2/3/..../16中按下的哪个按键值
		}
	}
	return 0;//没有按键按下时返回0
}

//矩阵按键:逐行扫描法
unsigned char KEY16_1(void)
{
	unsigned char x = 0;
	unsigned char y = 0;
	unsigned char n = 0;
	for ( x = 0; x < 4; x++)//共计4行扫描,4列接收
	{
		switch(x)//准备扫描x行
		{
			case 0:n=0xfe;break;
			case 1:n=0xfd;break;
			case 2:n=0xfb;break;
			case 3:n=0xf7;break;
			default:
				break;
		}
		key_all=n;
		if (key_all != n)//当有按键按下时
		{
			delay_ms(10);//消抖
			if (key_all != n)//确实有按键按下
			{
				switch (key_all & 0xf0)//判断是那列
				{
				case 0xe0:y = 0;break;
				case 0xd0:y = 1;break;
				case 0xb0:y = 2;break;
				case 0x70:y = 3;break;
				default:
					break;
				}
				while (key_all != n);//松手检测
				return key_true2[x][y];
			}
		}
	}
	return 0;
}
//矩阵按键:逐行扫描法
unsigned char KEY16_2(void)
{
	unsigned char x = 0;
	unsigned char y = 0;
	unsigned char n = 0;
	for ( x = 0; x < 4; x++)//共计4行扫描,4列接收
	{
		switch(x)//准备扫描x行
		{
			case 0:key_all=0xfe;break;
			case 1:key_all=0xfd;break;
			case 2:key_all=0xfb;break;
			case 3:key_all=0xf7;break;
			default:
				break;
		}
		delay_ms(20);//去抖动
		n=key_all&0xf0;
		key_all=0xff;//拉高所有按键
		if (n != 0xf0)//当有按键按下时
		{
			switch (n)//判断是那列
			{
				case 0xe0:y = 0;break;
				case 0xd0:y = 1;break;
				case 0xb0:y = 2;break;
				case 0x70:y = 3;break;
				default:
					continue;//如果按下多个按键,则无效,结束本次循环继续下次循环
			}
			while (key_all != 0xff);//松手检测
			return key_true2[x][y];
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

金丝草

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

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

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

打赏作者

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

抵扣说明:

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

余额充值