C语言矩阵键盘函数疑问
/* 键扫描函数 */uchar keyscan(void){ uchar scancode,tmpcode; P1 = 0xf0; // 发全0行扫描码 if ((P1&0xf0)!=0xf0) // 若有键按下 { delay(); // 延时去抖动 if ((P1&0xf0)!=0xf0) // 延时后再判断一次,去除抖动影响 { scancode = 0xfe; while((scancode&0x10)!=0) // 逐行扫描<此语句只检查第五位是否为1,如果最低列按下后不就等于零了,就跳过此函数了> { P1 = scancode; // 输出行扫描码 if ((P1&0xf0)!=0xf0) // 本行有键按下<为什么是行?哪一列按下此句都成立啊> { tmpcode = (P1&0xf0)|0x0f; /* 返回特征字节码,为1的位即对应于行和列 */ return((~scancode)+(~tmpcode)); } else scancode = (scancode<<1)|0x01; // 行扫描码左移一位 } } } return(0); // 无键按下,返回值为0 }
太给力了,很清楚。顺便问一下,我在知道里的提问,把WORD文字粘贴过来时总是没有换行,你看到的有换行吗?有什么办法可以解决,谢谢! 展开
看程序中P1.0-P1.3是行扫描输出,P1.4-P1.7是扫描输入。所以原理是P1.0-P1.3中每次只有一个引脚输出0,其余输出1,然后读取P1.4-P1.7是否有引脚为0;如果有0说明有按键按下,如果全1说明没有按键按下。
scancode这个变量就是用于控制P1.0-P1.3(P1 = scancode;由这句输出)中每次只有一个引脚输出0的。
scancode = 0xfe;这句中bit0值为0,其余bit为1,所以开始时,P1 = scancode;由这句输出后,P1.0为0,其余引脚为1。
scancode = (scancode << 1) | 0x01;这句使为0的bit左移一位(依次值为0xFE, 0xFD, 0xFB, 0xF7, 0xEF)。0xFE, 0xFD, 0xFB, 0xF7都满足while ((scancode &0x10) != 0)这个条件,而0xEF则不满足了,所以说<此语句只检查第五位是否为1,如果最低列按下后不就等于零了,就跳过此函数了>,到这就所有按键都扫描过了,没有按键按下(如果有按键按下,中途就返回了)。
if ((P1 &0xf0) != 0xf0)这句中P1 &0xf0表示只判断P1.4-P1.7,只有当前按下的按键所在行扫描输出为0时,这个表达式才成立(这时(P1 &0xf0) != 0xf0);否则这个表达式肯定不成立(这时(P1 &0xf0) == 0xf0),所以说当前行。
return ((~scancode) + (~tmpcode));这句就是如果有按键按下,那么直接返回键值,并不再进行循环退出程序。
程序格式要注意,下面这样更清楚:
uchar keyscan(void)
{
uchar scancode, tmpcode;
P1 = 0xf0; // 发全0行扫描码
if ((P1 &0xf0) != 0xf0)
// 若有键按下
{
delay(); // 延时去抖动
if ((P1 &0xf0) != 0xf0)
// 延时后再判断一次,去除抖动影响
{
scancode = 0xfe;
while ((scancode &0x10) != 0)
// 逐行扫描<此语句只检查第五位是否为1,如果最低列按下后不就等于零了,就跳过此函数了>
{
P1 = scancode; // 输出行扫描码
if ((P1 &0xf0) != 0xf0)
// 本行有键按下<为什么是行?哪一列按下此句都成立啊>
{
tmpcode = (P1 &0xf0) | 0x0f;
/* 返回特征字节码,为1的位即对应于行和列 */
return ((~scancode) + (~tmpcode));
}
else
scancode = (scancode << 1) | 0x01;
// 行扫描码左移一位
}
}
}
return (0); // 无键按下,返回值为0
}
没有换行。
程序还用word?.c文件也是文本文件,在文本文件中直接拷贝,可能就好了。