嵌入式硬件系统中通过简单的输入设备可以获取有用的信息,进行参数设置以及执行相关任务。
矩阵键盘是一种常用输入设备。
计算机三级嵌入式开发技术中,综合题常常出现填写矩阵键盘返回值的问题,所以就这让篇文章告诉你如何
即做得对,又做得快!
如果时间紧迫,可以不看原理分析,只看Summary即可
希望对你有所帮助!!!
关于矩阵键盘硬件上的知识,相信至少了解过51单片机的你已经有所熟悉了。
矩阵键盘就是采用行列矩阵形式构成键盘,利用行扫描法或反转法读取按键的特征值来决定按键的结果。
嵌入式考试用的是行扫描法。
接下来就来分析分析如何做得又对又快!
二、三眼速判法原理其实,方法的关键就是对于“&”、“|”以及“<<”运算的理解
以第3套为例
空已填好,重点部分也已加粗处理
设计一个键盘,键盘接口设计成4×4的阵列(其按键排列如图下所示)。键盘接口电路中选用GPEO~ GPE3来输出键盘行扫描信号,选用GPE4~ GPE7来输入键盘列信号。软件设计时设计者自行设计了键盘扫描函数,请你补充完善之:
//*KEYOUTPUT是键盘扫描时的输出地址,KEYINPUT是键盘读入时的地址
#define KEYOUTPUT (*(volatile INT8U *)0x56000044)
#define KEYINPUT (*(volatile INT8U *)0x56000044)
INT16U ScanKey()
{
INT16U key=0xFFFF;
INT16U i;
INT8U temp=0xFF,output;
//rGPECON是端口E的控制寄存器,其格式见后面附录
rGPECON=((rGPECON & 0xFFFFFF00) | 0x00000055);//初始化GPE0~GPE3为输出
rGPECON=rGPECON & 0xFFFF00FF;//初始化GPE4~GPE7为输入
//下面判断键盘中是否有键按下
for(i=1;((i0));i<<=1)
{
output |= 0xFF;
output &= (~i);
KEYOUTPUT = output;
temp = KEYINPUT;
if(temp & 0xF0) != 0xF0)//判断列信号是否为全“1"
{
key = (~i);
key <<= 8;
key |= ((temp & 0xF0) | 0x0F);//求得按键的返回值
return (key);//函数返回按键对应的值
}
}
return 0xFFFF;
}
应用程序中可根据上面的键盘扫描函数的返回值,来判断是否有按键按下,并确定是哪个按键按下。
若返回值为:0xFDBF时,可知是键盘中的“6”键按下,若返回值为:0xFE7F时,可知是键盘中的“确认“键被按下。
若无键按下时,返回值应为:0xFFFF。
我们逐行来看
#define KEYOUTPUT (*(volatile INT8U *)0x56000044)
#define KEYINPUT (*(volatile INT8U *)0x56000044)
这两行是宏定义,读取输出、输入值的地址,可以忽略
INT16U key=0xFFFF;
INT16U i;
INT8U temp=0xFF,output;
这里要注意的是数据类型:key 和 i 为16位二进制数,temp 和 output 为8位二进制数
用十六进制表示分别是4位十六进制数和2位十六进制数
rGPECON=((rGPECON & 0xFFFFFF00) | 0x00000055);//初始化GPE0~GPE3为输出
rGPECON=rGPECON & 0xFFFF00FF;//初始化GPE4~GPE7为输入
这里填的空是 0x00000055和0xFFFF00FF
这是常规的寄存器控制,在寄存器的赋值过程中,“&”用来“清0”,若保持其他位不变则“& 0xF”
而“|”用来“置1”,若保持其他位不变则“| 0x0”
for(i=1;((i0));i<<=1)
{
output |= 0xFF;
output &= (~i);
KEYOUTPUT = output;
temp = KEYINPUT;
这里填的空是i<<=1,这就涉及到了行扫描法的具体原理
四个I/O引脚GPE0~ GPE3作为行扫描输出,GPE4~ GPE7作为输入检测,先判断GPE0~ GPE3的哪个引角为低电平,再结合输出信号的行号即可得出对应键值。因为题中用GPE0~ GPE3作为行扫描信号(即输出信号),所以就要让这四个I/O口循环输出低电平。
这里给i赋值,每循环一次,i中的1就应该左移一位,依次是0001、0010、0100、1000,这样经过output |= 0xFF;
(全置1)和 output &= (~i);
(i取反)后,就可以保持GPE4~ GPE7不变,同时使GPE0~ GPE3依次为1110、1101、1011、0111,所以相应的循环条件就应该是"(i0)"。
那么现在,i的低两位就是GPE0~ GPE7的值“0x00Fn”(n是将按下键所在行置0,其他行为1对应的值,F为GPE4~ GPE7的值)
又因为output是8位,而i是16位,所以 output &= (~i);
过程中,高两位被舍弃,只剩下“0xFn”。
至此,输出信号值判断完毕,将其传给 KEYOUTPUT,然后接受输入信号KEYINPUT,传给temp。接下来开始判断输入信号。
if(temp & 0xF0) != 0xF0)//判断列信号是否为全“1"
这里填的空是0xF0
temp的值同样是8位,temp的低位(GPE0~ GPE3)因为“&0x0”可以忽略,所以关键就是看有没有按键按下。
若有按键按下,则GPE4~ GPE7必不为0,则高位就不会是“F”,temp的值也就不会是“0xF0”,就会执行if里的命令。
若没有按键按下,则继续等待,不会进入if的执行语句。
{
key = (~i);
key <<= 8;
有按键按下后,key是16位的,key = (~i);
这一命令得到的就是上文得到的输出信号的值。
经 key <<= 8;
左移8位后,输出信号的值在key的高两位,低两位补0,此时key的值为“0xFn00”
key |= ((temp & 0xF0) | 0x0F);//求得按键的返回值
注意,这里的temp经temp = KEYINPUT;
是输入信号的值,temp的低位"&0x_0" 再 "|0x_F"后,必为F(先不看高位,用_代替)
而高位 “&0xF_” 再 "|0x0_“后,(低位用_代替)其值保持不变,仍是temp的高位的值,也就是GPE4~ GPE7的值,按下键的所在列置0,其余列为1(这是硬件电路决定的)。
将temp的值与key按位或 key |= ((temp & 0xF0) | 0x0F);
因为temp是8位,key是16位,按位或后,保存下来的输入信号值就作为key的低两位保存了下来。其值为"0xFnmF”(n是行值,m是列值)
return (key);//函数返回按键对应的值
若有按键按下,返回key的值,值为"0xFnmF"。
return 0xFFFF;
如无按键按下,则返回0xFFFF。
(3)返回值答案至此,按键返回值的答案已经出来了,套用通式"0xFnmF"(n是行值,m是列值)
若按下"6":6在第二行(1101),第三列(1011),则对应的n为D,m为B。返回值是0xFDBF;
若按下"确认":确认在第一行(1110),第四列(0111),则对应的n为E,m为7。返回值是0xFE7F。
若无键按下时,返回值应为:0xFFFF。
但是,这个通式不是所有题都适用的,因为题会变!!!
比如第9套的输入输出就反过来了。所以,来看看总结吧!(仅针对按键返回值)
之所以称之为三眼快速判断法,是因为只需要关注三个点:
1.输入信号、输出信号都是哪些引脚?
2.按下的键在第几行? 填写至返回值高两位
output &= (~i);
这一行是该步最该关注的代码,以判断F在第几位
高两位贮存的是作为输出信号的值,因为经过程序左移8后,必定在最高位,且取反后必有一位为F,另一位要看按下的键是在第几行,将所在行对应的位置0,其余为1,再将该值用十六进制表示。
但要看清题,若0-3为输出,则F在返回值的第三位;若4-7为输出,则F在返回值的第三位(以第3,9套题举例)。
3.按下的键在第几列? 填写至返回值低两位
(temp & 0xF0) | 0x0F;
这一行是该步最该关注的代码,以判断F在第几位
低两位贮存的是作为输入信号的值,因为最后一条语句就是对temp的操作,所以低两位必有一位为F,另一位要看按下的键是在第几列,将所在列对应的位置0,其余为1,再将该值写成十六进制形式。
同理,应注意,若4-7为输入,则最后一位为F,若0-3为输入,则第二位为F。
综上,按照以上三步就可以快速写出按键的返回值了!
除此以外,具体情况具体分析,做对题的关键还是要认真看题!!!
最后如有误解或什么不足之处,欢迎大家指正
如还有其他嵌入式相关问题也欢迎大家留言交流
如果此文你有帮助,可以点赞哦!