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;
}