矩阵键盘
一.基础知识
- 在键盘中按键数量较多时,为了减少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按键计数的功能!