键盘在单片机体系中用得十分广泛。当按键多并且单片机的I/O口有限时,往往要考虑的是矩阵式键盘。其中有两种办法能够完结矩阵式键盘:一种是运用纯硬件完结解码的称为“编码键盘”;其他一种是运用软件完结解码的称为“非编码键盘”。
在单片机体系中,只需单片机有空余的时刻来解码时,咱们往往运用的是软件解码的办法,即“非编码键盘”来完结矩阵键盘。这样能够节省本钱。下面我就对矩阵键盘在51单片机中的软件解码办法运用总结一下。
原理图:
作业原理:
扫描程序查询的内容如下:
&129;查询是否有键按下。首要单片机向行扫描口P1.0~P1.3输出全为0的扫描码F0H,然后从列检测口P1.4~P1.7输入列检测信号,只需有一列信号不为1,即P1口不为F0H,则表明有键按下。接着要查出按下键地点的行、列方位。
&8218;查询按下键地点的行、列方位。单片机将得到的信号取反,P1.4~P1.7口中为1的方位便是键地点方位。
接下来要确认键地点的行,需进行行逐行扫描。单片机首要运用P1.0口接地,P1.1~P1.7口为1,即向P1口发送扫描码FEH,接着输入列检测信号,若为全1,则表明不在榜首行。然后使P1.1接地,其他为1,再读入列信号……。这样逐行发0扫描码,直到找到按键地点的行,将该行扫描码取反保存。若各行都扫描今后仍没有找到,则抛弃扫描,认为是键的误动作。
&402;对得到的行号和列号译码,得到键值。
&8222;键的消抖处理。当用手按下一个键时,往往会呈现所按键在闭合方位和断开方位之间跳几下才安稳到闭合状况的状况;在开释一个键时,也会呈现相似的状况。这便是键颤动。颤动的继续时刻纷歧,一般不会大于10ms。若颤动问题不处理,就会引起对闭合键的屡次读入。处理键颤动最便利的办法是:当发现有键按下后,不要当即进行逐行扫描,而是延时10ms后再进行。因为键按下的时刻会继续上百ms,延时后再扫描也不迟。
程序如下:
unsignedcharkey_scan(void)//按键扫描函数
{
unsignedcharsccode,recode;
P1=0xf0;//发全0行扫描码,列线输入
if((P1&0xf0)!=0xf0)//若有键按下
{
delay_ms(10);//延时去抖
if((P1&0xf0)!=0xf0)
{
sccode=0xfe;//逐行扫描初值
While((sccode&0x10)!=0)
{
P1=sccode;//输出行扫描码
if((P1&0xf0)!=0xf0)//本行有键按下
{
recode=(P1&0xf0)|0xf0;
return((~sccode)+(~recode));//回来特征字节码
}
else
sccode=(sccode<<1)|0x01;//行扫描码左移一位
}
}
}
return(0);//无键按下,回来值为0
}
阐明:
此按键扫描函数是许多书上介绍的按键扫描函数,从本来的视点来说是完全正确可行的。但是在我前次做《密码锁》时,发现用此函数比较费事,且总是存在一些问题。经过查阅很多书本和试验,我写出了比较简单并且切实可行的按键扫描程序。
程序如下:
/*****************************************************
函数名:ucharKey_scan(void)
功用:4×4按键,按键扫描
阐明:对按键进行扫描,然后得到键编码
进口参数:无
回来值:有键按下回来:键编码=行扫描值+列扫描值;无按键回来0
*****************************************************/
ucharKey_scan(void)
{
ucharkey;//寄存键编码
P1=0xf0;//发全0行扫描码,列线输入
if((P1&0xf0)!=0xf0)//若有键按下
{
delay_ms(10);//延时去抖
P1=0xf0;//取高4位值.即:列扫描值
key=P1&0xf0;//寄存键编码的高4位
P1=0x0f;//取低4位值.即:行扫描值
key=(P1&0x0f)|key;//低4位与高4位进行兼并
if(key!=0xff)
{
return(key);//有键按下,回来键编码
}
}
return(0);//无键按下,回来0
}
/*****************************************************
函数名:ucharKey_switch(void)
功用:按键转化程序
阐明:对按键码进行转化
进口参数:无
回来值:ASCII码
*****************************************************/
ucharKey_switch(void)
{
ucharkey;
key=Key_scan();
switch(key)
{
case0xee:return(49);break;/*”1″键*/
case0xed:return(50);break;/*”2″键*/
case0xeb:return(51);break;/*”3″键*/
case0xe7:return(65);break;/*”A”键*/
case0xde:return(52);break;/*”4″键*/
case0xdd:return(53);break;/*”5″键*/
case0xdb:return(54);break;/*”6″键*/
case0xd7:return(66);break;/*”B”键*/
case0xbe:return(55);break;/*”7″键*/
case0xbd:return(56);break;/*”8″键*/
case0xbb:return(57);break;/*”9″键*/
case0xb7:return(67);break;/*”C”键*/
case0x7e:return(42);break;/*”*”键*/
case0x7d:return(48);break;/*”0″键*/
case0x7b:return(35);break;/*”#”键*/
case0x77:return(68);break;/*”D”键*/
case0x00:return(00);break;/*”无”键*/
}
}
/*接盘按键阐明:
————————————————–
|1|2|3|A|
————-
|4|5|6|B|
————-
|7|8|9|C|
————-
|*|0|#|D|
————————————————–
阐明:
假如需求更改按键值,只需改Key_switch()函数中对应的回来值即可。关于延时函数比较简单只需一个for循环即可,所以在这里就没写出来。因每个单片机的I/O的运用是纷歧样的,所以自己写的这个函数只能在51单片机体系下运转。假如要在其他单片机体系下,或许需求用榜首种进行改善。