//**keyoutput是键盘扫描时的输出地址,keyinput是键盘读入时的地址
#define KEYOUTPUT(*(volatile INT8U*)0x56000044)//定义GPE的数据端口
#define KEYINPUT(*(volatile INT8U*)0x56000034) //定义GPD的数据端口
INT16U ScanKey(){
INT16U key=0xFFFF;
INT16U i;
INT8U temp=0xFF,output;
rGPDCON = rGPDCON & 0xFFFFFFC0;//初始化GPD0~GPD2为输入
rGPECON = ((rGPECON & 0xFFFFFF00)|0x00000055);//初始化GPE0~GPE3为输出;
for (i=1;((i<=8) && (i>0)); i<<=1)
{
output |= 0xFF;
output &= (~i);
KEYOUTPUT=output;
temp = KEYINPUT;
if ((temp&0x07)!=0x07){
key = (~i);
key <<= 8;
key |= (temp&0x07)|0xF8);
return (key);
}
}
return 0xFFFF;
}
其实底层逻辑相当简单,通过不停的左移i,然后取反,依次拉低每一行的GPIO。随后在拉低每一行后检查是否有某一列同时被拉低,如果有将列数据记录在[0:2],最后合并一下列数据和行数据,每一个按键就会有一个独特的16位数字相匹配了。
这样其实可以增加I/O口的利用资源,无需一个按键对应一个I/O口了