蓝桥杯单片机矩阵键盘消抖(利用三行代码)

三行代码

keycode = ~(keycloumn | keyrow);
key = keycode & (keycode ^ keybefore);
keybefore = keycode;

三行代码理解:

一般情况不会同时按下两个及以上的按键,以下不考虑同时按下不同按键的情况。

keycode为当前扫描得到的按键编码,有按键按下不为0,否则为0,keybefore为上一次扫描时得到的按键值。

第一行是按键编码取反,将按下的按键所在行和列二进制值取1,(如按下第一行第二列keycode为0x41, 高四位从高位到低位对应第一列到第四列,低四位从低位到高位对应第一行到第四行);

第二行是松手检测加消抖。当前和上一次扫描时按键的状态有四种情况,为消抖,只在情况②(刚刚按下按键)时读取按键编码
①:上一次未按下,当前未按下;
②:上一次未按下,当前按下;
③:上一次按下,当前按下;
④:上一次按下,当前已经松手;

异或运算即不相同为1,相同为0,只有②和④两种情况keycode与keybefore不相同,因此只有②和④两种情况keycode^keybefore不为0。这两种情况都是一个为0的值与一个不为0的值位异或,那么②和④两种情况下 keycode ^ keybefore的值等于不为0的那个值(比如0x87 ^ 0x00 = 0x87),所以只有情况②和④keycode ^ keybefore = keycode(当前扫描时按键编码)。异或得到的值还得与keycode进行位与操作,情况④keycode = 0,与(keybefore ^ keycode)位与结果为0,但是情况②keycode为当前按下按键编码,而(keybefore ^ keycode)也为当前按下按键编码,因此key也为当前按下按键编码。综上,只有情况②key的值为当前按下按键编码,其余三种情况key = 0。

第三行:
保存上一次按下按键编码。

源代码

#include<stc15f2k60s2.h>

#define uchar unsigned char

code uchar semg[12] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90,
											 0xbf, 0xff};
code uchar semg_bit[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
uchar semg_temp[8] = {11, 11, 11, 11, 11, 11, 11, 11};

//自定义按键排列,-1表示按键无效显'-'
code char keymap[4][4] = {{0, 1, 2, -1}, {3, 4, 5, -1}, {6, 7, 8, -1}, {9, 10, 11, -1}};


void allinit()
{
	P2 = 0x80;	P0 = 0xff;
	P2 = 0xa0;	P0 = 0x00;
	P2 = 0xc0;	P0 = 0xff;
	P2 = 0xe0;	P0 = 0xff;
}


void Timer0Init(void)		//2毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x9A;		//设置定时初值
	TH0 = 0xA9;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	EA = 1;
	ET0 = 1;
}


void display()
{
	uchar i;
	
	P2 = 0xe0;	P0 = semg[semg_temp[i]];
	P2 = 0xc0;	P0 = semg_bit[i];
	P2 = 0x00;	P0 = 0xff;
	
	i++;
	if(i == 8)
		i = 0;
}


void fun() interrupt 1
{
	display();
}


char keyscan()
{
	static uchar keybefore = 100;
	char keyvalue = 100;
	uchar keyrow = 0, keycloumn = 0, keycode = 0, key = 0, i = 0, j = 0;
	
	P3 = 0x0f;	P44 = 0;	P42 = 0;	P35 = 0;
	keyrow = P3 & 0x0f;
	P3 = 0xf0;	P44 = 1;	P42 = 1;	P35 = 1;
	if(P44 == 0)				keycloumn = 0x70;
	else if(P42 == 0)		keycloumn = 0xb0;
	else								keycloumn = P3 & 0xf0;
	
	//以下为三行代码
	keycode = ~(keycloumn | keyrow);
	key = keycode & (keycode ^ keybefore);
	keybefore = keycode;
	
	if(key)
	{
		for(i = 0; i < 4; i++)
			for(j = 0; j < 4; j++)
				if(key == (0x80 >> j | 0x01 << i))
				{
					keyvalue = keymap[i][j];
					break;
				}
	}
	
	return keyvalue;
}


void menu(char keyvalue)
{
	if(keyvalue >= 0 && keyvalue <= 11)
	{
		if((keyvalue / 10) > 0)
			semg_temp[6] = keyvalue / 10;
		else
			semg_temp[6] = 11;
		semg_temp[7] = keyvalue % 10;
	}
	else if(keyvalue == -1)
	{
		semg_temp[6] = 11;
		semg_temp[7] = 10;
	}
	else	;
}


void main()
{
	allinit();
	Timer0Init();
	
	while(1)
	{
		menu( keyscan() );
	}
}
  • 26
    点赞
  • 88
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
蓝桥杯单片机矩阵键盘是一种常见的输入设备,它可以通过按下不同的按键来输入不同的信息。下面是蓝桥杯单片机矩阵键盘的工作原理和实现方法: 1.工作原理: 蓝桥杯单片机矩阵键盘的工作原理是基于按键扫描的。按键扫描的思路是,按键是连接行和列的桥梁,如果往某行或者某列输入低电平,其他行或列为高电平,我们只需要检测所有列或者行是否有低电平即可。因此,我们可以通过按下按键来改变行列的电平状态,从而检测出按下的按键。 2.实现方法: 蓝桥杯单片机矩阵键盘的实现方法如下: (1)将矩阵键盘的行和列分别连接到单片机的IO口上。 (2)设置行为输出,列为输入。 (3)将所有列的电平设置为高电平。 (4)循环扫描每一行,将该行的电平设置为低电平,然后检测所有列的电平状态,如果有低电平,则说明该行对应的按键被按下。 (5)重复步骤(4),直到检测完所有行。 下面是一个简单的蓝桥杯单片机矩阵键盘的实现代码: ```c #include <reg52.h> sbit row1 = P1^0; sbit row2 = P1^1; sbit row3 = P1^2; sbit row4 = P1^3; sbit col1 = P1^4; sbit col2 = P1^5; sbit col3 = P1^6; sbit col4 = P1^7; void main() { while(1) { row1 = 0; row2 = 1; row3 = 1; row4 = 1; if(col1 == 0) { /* 检测到第1个按键被按下 */ } if(col2 == 0) { /* 检测到第2个按键被按下 */ } if(col3 == 0) { /* 检测到第3个按键被按下 */ } if(col4 == 0) { /* 检测到第4个按键被按下 */ } row1 = 1; row2 = 0; row3 = 1; row4 = 1; if(col1 == 0) { /* 检测到第5个按键被按下 */ } if(col2 == 0) { /* 检测到第6个按键被按下 */ } if(col3 == 0) { /* 检测到第7个按键被按下 */ } if(col4 == 0) { /* 检测到第8个按键被按下 */ } row1 = 1; row2 = 1; row3 = 0; row4 = 1; if(col1 == 0) { /* 检测到第9个按键被按下 */ } if(col2 == 0) { /* 检测到第10个按键被按下 */ } if(col3 == 0) { /* 检测到第11个按键被按下 */ } if(col4 == 0) { /* 检测到第12个按键被按下 */ } row1 = 1; row2 = 1; row3 = 1; row4 = 0; if(col1 == 0) { /* 检测到第13个按键被按下 */ } if(col2 == 0) { /* 检测到第14个按键被按下 */ } if(col3 == 0) { /* 检测到第15个按键被按下 */ } if(col4 == 0) { /* 检测到第16个按键被按下 */ } } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值