CD107D开发板原理图中的矩阵键盘如图所示,乍一看好像没什么问题,写程序一测试,咦不对啊,键值怎么不对呢?这里有个小坑,原理图上给的是个是STC89C52连接的引脚,而我们实际用的是IAP15F61S2的转接板,其中P36和P37引脚位置换成了P42,P44。
转接板如下
到这里有的同学可能有些不知所措,因为当初学习51矩阵键盘是直接接到一个P端口的,可以直接读取端口,再转化为键值,现在引脚换了,还能那样写吗? 当然不能!
既然不能按照以前学习那种方法写,那我们就换种方式,我们从矩阵键盘键值扫描原理出发,无非是分别扫描行和列,然后得到唯一键值,在得到键值后按照传统的方式我们必须进行消抖处理,一般我们采用软件消抖,更加方便,常规操作就是延时重复判断是否按下,这种方式在任务较少的情况下很实用,但如果在你的主线程存在着十几个任务,那么如果不引入操作系统来管理,那么任何一个任务都不宜添加任何影响其他任务的延时操作。
在这里针对按键扫描处理我们用状态转移法,就像前面数码管处理方式一样,如果一次性处理不完,我们可以选择分多次进行,具体来说,当有按键按下时,我把键值存下来,但不进行处理,待下次再执行到这里进行键值的任务处理,处理完后再次将状态转移,当再下次任务到来时如果键值已经消失,那么将状态恢复到初始时。听起来比较绕,直接看代码吧
声明:
#include "key.h" #include "basic.h" //行定义 sbit r1=P3^0; sbit r2=P3^1; sbit r3=P3^2; sbit r4=P3^3; //列定义 sbit c1=P4^4; sbit c2=P4^2; sbit c3=P3^5; sbit c4=P3^4; u8 keybuf=0;//存储键值
函数:
void key(void) { static keystate=0,a=0,b=1; r1=r2=r3=r4=0; c1=c2=c3=c4=1; if(!c1)a=1; else if(!c2)a=2; else if(!c3)a=3; else if(!c4)a=4; else if(c1&&c2&&c3&&c4)a=0; r1=r2=r3=r4=1; c1=c2=c3=c4=0; if(!r1)b=1; else if(!r2)b=2; else if(!r3)b=3; else if(!r4)b=4; else if(r1&&r2&&r3&&r4)b=1; keybuf=a+b*4-4; r1=r2=r3=r4=1; c1=c2=c3=c4=1; //采集完按键必须把所有按键恢复 switch(keystate) { case 0: if(keybuf!=0) keystate=1; break; case 1: switch(keybuf) { case 1: buff[0]=1; break; case 2: buff[0]=2; break; default: break; } keystate=2; break; case 2: if(keybuf==0) keystate=0; break; } }
通过以上代码,将一次按键处理分三次执行完毕,并且由于没有任何冗余的延时函数,直接放到中断中也是OK滴,放在循环中的话,最好有其他任务进行缓冲,以保证相邻两次调用时间间隔不会太短,经过我实际测试,识别准确度还是可以的,在使用过程中还没有出现过错误识别。