当前位置:   article > 正文

【蓝桥杯_学习_51单片机】矩阵键盘 状态机法_51单片机状态机

51单片机状态机

矩阵键盘

一.基础知识

  • 在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式
  • 采用逐行或逐列的“扫描”,就可以读出任何位置按键的状态
    矩阵键盘和独立按键一样,也需要进行消抖处理!
    于此补充一下抖动的含义:

对于机械开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开,所以在开关闭合及断开的瞬间会伴随一连串的抖动

20230130_1

消抖的话,我们采用两种方式:

状态机法三行按键法

后面会详细介绍!
20230130_2

上图是矩阵键盘的电路图,我们通过电路图来对矩阵键盘的IO口进行分析!
其中P30,P31,P32,P33来控制矩阵键盘的行,P34,P35,P42,P44来控制矩阵键盘的列。

接下来介绍一下我们的编程思路:
(1) 给控制矩阵键盘的四位赋值为0,检测控制矩阵键盘的四位中哪一位为0,由此确定按键所在
(2) 给控制矩阵键盘的四位赋值为0,检测控制矩阵键盘的四位中哪一位为0,由此确定按键所在
(3) 根据行和列,确定按键的位置
选(1)(2)中(1)步骤来进行分析:

P30=0,P31=0,P32=0,P33=0;
P34=1,P35=1,P42=1,P44=1;
//可以看出上述赋值操作略微有些繁琐,我们进行简化
P3 = 0xF0;
P4 = 0xFF;
//这样赋值可以实现异曲同工之妙!
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

赋值之后,进行选择判断操作

if(P34==0){
    //...
}
if(P35==0){
    //...
}
if(P44==0){
    //...
}
if(P44==0){
    //...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

获取键值

关键代码如下:

//矩阵键盘_获取键值
u8 KBD_KeyIO()
{
	u8 key_io = 0;
	P3 = 0xf0,P4 = 0xff;	//列扫描,低四位输出0,读取高四位的值
	if(P44==0)
	{
		key_io = 4;
	}
	if(P43==0)
	{
		key_io = 8;
	}
	if(P35==0)
	{
		key_io = 12;
	}
	if(P34==0)
	{
		key_io = 16;
	}
	
	P3 = 0x0f,P4 = 0x00;//行扫描,高四位输出0,读取低四位的值
	if(P33==0)
	{
		key_io = key_io + 0;
	}
	if(P32==0)
	{
		key_io = key_io + 1;
	}
	if(P31==0)
	{
		key_io = key_io + 2;
	}
	if(P30==0)
	{
		key_io = key_io + 3;
	}
	return key_io;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

状态机

状态转移图如下:
20230202_1
状态机法代码如下:

//矩阵键盘 - 状态机法
u8 vKBD_KeyIO()
{
	u8 key_io = 0;
	P3 = 0xf0;P4 = 0xff;	//列扫描
	if(P44==0) key_io = 4;
	if(P42==0) key_io = 8;
	if(P35==0) key_io = 12;
	if(P34==0) key_io = 16;
	
	P3 = 0x0f;P4 = 0x00;	//行扫描
	if(P33==0) key_io += 0;
	if(P32==0) key_io += 1;
	if(P31==0) key_io += 2;
	if(P30==0) key_io += 3;
	
	return key_io;
}

#define KEY_NO 0	//无按键状态
#define KEY_DOWN 1	//有按键按下状态,判断是否为抖动
#define KEY_UP 2	//等待松手状态,判断是否弹起
u8 vKBD_Read_State()
{
	static u8 key_state = 0;
	u8 key_io = 0,key_return = 0;
	key_io = vKBD_KeyIO();
	switch(key_state)
	{
		case KEY_NO:						//无按键状态,用于判断是否按下
			if(key_io) key_state = KEY_DOWN;
		break;
		case KEY_DOWN:						//有按键按下状态,判断是否为抖动
			if(key_io)
			{
				key_state = KEY_UP;
				key_return  = key_io;
			}
			else
			{
				key_state = KEY_NO;
			}
		break;
		case KEY_UP:
			if(key_io == 0)					//等待松手状态,判断是否弹起
			{
				key_state = KEY_NO;
			}
		break;
	}
	return key_return;
}

//矩阵键盘处理函数
u8 cnt_kbd;
u8 s4_number;
u8 key_val;
void vKBD_Process(void)
{
	if(cnt_kbd>=10)
	{
		cnt_kbd = 0;
		key_val = vKBD_Read_State();
		if(key_val==4)
		{
			s4_number++;
		}
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

以上核心代码实现了检测按键和S4按键计数的功能!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/408786
推荐阅读
相关标签
  

闽ICP备14008679号