矩阵键盘
一.基础知识
- 在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式
- 采用逐行或逐列的“扫描”,就可以读出任何位置按键的状态
 矩阵键盘和独立按键一样,也需要进行消抖处理!
 于此补充一下抖动的含义:
对于机械开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开,所以在开关闭合及断开的瞬间会伴随一连串的抖动

消抖的话,我们采用两种方式:
状态机法 和 三行按键法
后面会详细介绍!
 
上图是矩阵键盘的电路图,我们通过电路图来对矩阵键盘的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;
//这样赋值可以实现异曲同工之妙!
赋值之后,进行选择判断操作
if(P34==0){
    //...
}
if(P35==0){
    //...
}
if(P44==0){
    //...
}
if(P44==0){
    //...
}
获取键值
关键代码如下:
//矩阵键盘_获取键值
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;
}
状态机法
状态转移图如下:
 
 状态机法代码如下:
//矩阵键盘 - 状态机法
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++;
		}
	}
}
以上核心代码实现了检测按键和S4按键计数的功能!



















