行列矩阵扫描多按键识别问题
最近做的PC键盘,需要处理多按键识别问题,键盘口使用8x11矩阵方式。目前的情况是,在同一行上的键,多键按下能识别,不同行上的键多键被按下会出现误判情况。
尝试过扫描本行时,把其它行端口设为高阻输入无上拉模式,也会出现误判情况,俗称的“鬼影”
论坛里有人做过相关的经验可以分享交流下吗?
我的多键识别代码如下:
void MainKeyPressScan(void)
{
u32 KeyData;
if( MainKeyPressStructure.KeyScanEnable == DISABLE )
return;
MainKeyPressStructure.KeyScanEnable= DISABLE;
MainKeyPressStructure.KeyScanTime1ms = 0;
KeyData = GetMainKeyPort();
if( KeyData != MainKeyPressStructure.KeyPressCode ) //按键有变化
{
MainKeyPressStructure.KeyPressCode = KeyData; //取数据
MainKeyPressStructure.KeyDebounce = KEY_DEBOUNCE_TIME; //开始抖动
}
else
{
if( MainKeyPressStructure.KeyDebounce )
{
MainKeyPressStructure.KeyDebounce--;
if( MainKeyPressStructure.KeyDebounce == 0)
{
MainKeyPressStructure.KeyPressCode = KeyData;
MainKeyPressStructure.KeyPressSuccess= SUCCESS;
}
}
}
}
//矩阵扫描部分代码,P0口做扫描数据口,P2口和P7.5-7做按键返回数据口。
#define KEY_SCAN_LINE1_DATA ~0x01 //第1行扫描数据
#define KEY_SCAN_LINE2_DATA ~0x02 //第2行扫描数据
u32 GetMainKeyPort(void)
{
u8 KeyTempPort2,KeyTempPort7;
u16 KeyReturnData;
u32 KeyResult,KeyPressData;
KeyResult = 0;
SetPort0Mode(KEY_SCAN_LINE1_DATA, 0, ~KEY_SCAN_LINE1_DATA); //P00设为准双向口+上拉电阻,其它的设为高祖输入+无上拉电阻
IO_KeyDelay(IO_KEY_DELAY_TIME);
KeyPressData = MAIN_KEY_WAS_NOT_PRESSED;
KEY_IO_SCAN_PORT0 = KEY_SCAN_LINE1_DATA; //扫描第1行按键
IO_KeyDelay(IO_KEY_DELAY_TIME);
KeyTempPort2 = KEY_IO_RETURN_PORT2; //读取按键返回值
KeyTempPort7 = KEY_IO_RETURN_PORT7; //读取按键返回值
KeyTempPort7 = ( KeyTempPort7 & KEY_RETURN_PORT7_MARSK ) >> 5;
KeyTempPort7 |= 0xF8;
KeyReturnData = ~((((u16)KeyTempPort7) << 8) | (u16)KeyTempPort2);
if( KeyReturnData != MAIN_KEY_WAS_NOT_PRESSED )
{
KeyPressData = ~KEY_SCAN_LINE1_DATA; //处理第1行按键数据
KeyPressData = ( KeyPressData << 16 ) | (u32)KeyReturnData;
KeyResult |= KeyPressData;
}
SetPort0Mode(KEY_SCAN_LINE2_DATA, 0, ~KEY_SCAN_LINE2_DATA);
IO_KeyDelay(IO_KEY_DELAY_TIME);
KeyPressData = MAIN_KEY_WAS_NOT_PRESSED;
KEY_IO_SCAN_PORT0 = KEY_SCAN_LINE2_DATA; //扫描第2行按键
IO_KeyDelay(IO_KEY_DELAY_TIME);
KeyTempPort2 = KEY_IO_RETURN_PORT2; //读取按键返回值
KeyTempPort7 = KEY_IO_RETURN_PORT7; //读取按键返回值
KeyTempPort7 = ( KeyTempPort7 & KEY_RETURN_PORT7_MARSK ) >> 5;
KeyTempPort7 |= 0xF8;
KeyReturnData = ~((((u16)KeyTempPort7) << 8) | (u16)KeyTempPort2);
if( KeyReturnData != MAIN_KEY_WAS_NOT_PRESSED )
{
KeyPressData = ~KEY_SCAN_LINE2_DATA; //处理第2行按键数据
KeyPressData = ( KeyPressData << 16 ) | (u32)KeyReturnData;
KeyResult |= KeyPressData;
}
}
在处理8x11矩阵键盘的多按键识别问题时,您遇到的“鬼影”现象(即不同行上的多键按下时出现误判)是一个常见的技术挑战。这种现象通常是由于矩阵扫描时,电流通过未被激活的行或列,导致误触发。以下是一些可能的解决方案和优化建议:
1. 二极管隔离
在键盘矩阵的每个按键上添加二极管,可以有效地防止电流反向流动,从而避免“鬼影”现象。二极管的方向应确保电流只能从行流向列,或从列流向行,具体取决于您的扫描方式。
2. 改进扫描算法
您的扫描代码可以进一步优化,以确保在扫描某一行时,其他行处于高阻状态,并且没有上拉电阻。以下是一个改进的扫描算法示例:
c
void MainKeyPressScan(void) {
u32 KeyData;
if (MainKeyPressStructureKeyScanEnable == DISABLE)
return;
MainKeyPressStructureKeyScanEnable = DISABLE;
MainKeyPressStructureKeyScanTime1ms = 0;
for (int row = 0; row < 8; row++) {
// 激活当前行
SetRowActive(row);
// 读取列数据
KeyData = GetColumnData();
// 处理按键数据
if (KeyData != MainKeyPressStructureKeyPressCode) {
MainKeyPressStructureKeyPressCode = KeyData;
MainKeyPressStructureKeyDebounce = KEYDEBOUNCETIME;
} else {
if (MainKeyPressStructureKeyDebounce) {
MainKeyPressStructureKeyDebounce--;
if (MainKeyPressStructureKeyDebounce == 0) {
// 处理按键事件
ProcessKeyPress(MainKeyPressStructureKeyPressCode);
}
}
}
// 关闭当前行
SetRowInactive(row);
}
}
3. 去抖动处理
按键抖动是另一个常见问题,可能导致误判。您可以在硬件或软件层面进行去抖动处理。软件去抖动通常通过延时和多次采样来实现。以下是一个简单的去抖动处理示例:
c
define DEBOUNCETIME 20 // 去抖动时间,单位为毫秒
void DebounceKeyPress(u32 KeyData) {
static u32 LastKeyData = 0;
static u32 DebounceCounter = 0;
if (KeyData != LastKeyData) {
DebounceCounter = DEBOUNCETIME;
LastKeyData = KeyData;
} else {
if (DebounceCounter > 0) {
DebounceCounter--;
if (DebounceCounter == 0) {
// 处理按键事件
ProcessKeyPress(KeyData);
}
}
}
}
4. 硬件设计优化
在硬件设计上,确保矩阵的行和列之间有足够的隔离,避免信号串扰。使用高质量的PCB材料和合理的布线设计,可以减少信号干扰和误触发。
5. 使用专用芯片
如果上述方法仍无法解决问题,可以考虑使用专用的键盘扫描芯片。这些芯片通常内置了多按键识别和去抖动功能,可以大大简化软件设计和提高系统可靠性。
6. 调试与测试
在实际应用中,调试和测试是确保系统稳定性的关键。使用逻辑分析仪或示波器,可以实时监控矩阵扫描过程中的信号变化,帮助定位和解决问题。
总结
通过上述方法,您可以有效地解决8x11矩阵键盘的多按键识别问题,避免“鬼影”现象。具体实施方案需要根据您的硬件设计和应用需求进行调整。希望这些建议对您有所帮助,祝您的项目顺利成功!
[本文内容由国芯人工智能辅助生成,仅供参考] 在处理PC键盘的多按键识别问题时,尤其是采用8x11矩阵扫描的方式,确实会遇到“鬼影”(Ghosting)问题。这是由于矩阵扫描的物理特性导致的,特别是在不同行上的按键同时按下时,可能会出现误判。以下是一些专业的建议和解决方案,帮助你优化代码并解决这一问题。
1. 理解“鬼影”问题的根源
“鬼影”问题通常是由于矩阵扫描中的电气特性导致的。当多个按键按下时,电流可能会通过未预期的路径流动,导致误判。具体来说,当不同行和列上的按键同时按下时,可能会形成一个“虚拟”的按键,从而产生误判。
2. 优化扫描算法
为了避免“鬼影”问题,可以采取以下优化措施:
a. 逐行扫描
在扫描某一行时,将该行的输出设置为低电平,同时将所有其他行的输出设置为高阻态或高电平。这样可以确保只有当前行的按键状态被读取,避免其他行的干扰。
b. 使用二极管隔离
在矩阵的每个按键上添加一个二极管,可以防止电流反向流动,从而避免“鬼影”问题。这种方法虽然增加了硬件成本,但能有效解决多按键识别问题。
c. 软件去抖
在读取按键状态后,加入去抖处理,可以有效避免由于按键抖动导致的误判。你已经在代码中实现了去抖处理,这是正确的做法。
3. 代码优化建议
基于上述分析,以下是代码的优化建议:
c
void MainKeyPressScan(void)
{
u32 KeyData;
if (MainKeyPressStructureKeyScanEnable == DISABLE)
return;
MainKeyPressStructureKeyScanEnable = DISABLE;
MainKeyPressStructureKeyScanTime1ms = 0;
// 逐行扫描
for (int row = 0; row < 8; row++) {
// 设置当前行为低电平
SetRowLow(row);
// 读取列数据
KeyData = GetMainKeyPort();
// 处理按键状态
if (KeyData != MainKeyPressStructureKeyPressCode) {
MainKeyPressStructureKeyPressCode = KeyData;
MainKeyPressStructureKeyDebounce = KEYDEBOUNCETIME;
} else {
if (MainKeyPressStructureKeyDebounce) {
MainKeyPressStructureKeyDebounce--;
if (MainKeyPressStructureKeyDebounce == 0) {
// 处理稳定的按键状态
ProcessKeyPress(MainKeyPressStructureKeyPressCode);
}
}
}
// 恢复当前行为高阻态或高电平
SetRowHigh(row);
}
MainKeyPressStructureKeyScanEnable = ENABLE;
}
void SetRowLow(int row) {
// 设置指定行为低电平,其他行为高阻态或高电平
// 具体实现取决于硬件设计
}
void SetRowHigh(int row) {
// 恢复指定行为高阻态或高电平
// 具体实现取决于硬件设计
}
void ProcessKeyPress(u32 keyCode) {
// 处理稳定的按键状态
// 具体实现取决于应用需求
}
4. 硬件设计建议
除了软件优化,硬件设计也是解决“鬼影”问题的关键。以下是一些硬件设计建议:
a. 使用二极管隔离
如前所述,在矩阵的每个按键上添加二极管,可以有效防止电流反向流动,避免“鬼影”问题。
b. 增加上拉电阻
在列线上增加上拉电阻,可以确保在未按下按键时,列线处于高电平状态,从而避免误判。
c. 优化PCB布局
合理的PCB布局可以减少电气干扰,降低“鬼影”问题的发生概率。确保行线和列线之间的间距足够大,避免交叉干扰。
5. 测试与验证
在优化代码和硬件设计后,建议进行充分的测试,确保多按键识别功能正常工作。测试时,可以模拟各种按键组合,特别是不同行上的按键同时按下的情况,验证是否会出现“鬼影”问题。
总结
通过逐行扫描、使用二极管隔离、软件去抖以及优化硬件设计,可以有效解决8x11矩阵键盘的多按键识别问题,避免“鬼影”现象。希望以上建议能帮助你优化键盘设计,提升用户体验。如有进一步问题,欢迎继续交流。
[本文内容由国芯人工智能辅助生成,仅供参考] 原理图建议也上传下,有没有楼上说的二极管 没有二极管隔离,最初设计时没考虑要多个按键情况。
矩阵8x11,8各行扫描使用P0口,11个列扫描使用P2口和P7口的4、5、6位,没有二极管隔离。
单个键没问题。同一个行扫描信号所在的键也可以识别多个按键,不同行扫描信号所在的键识别有误。 改硬件的话,在每行扫描信号加入MOS管(总共8个),扫描该行时,MOS管打开,其它的行MOS管关闭,这个应该可以解决“鬼影”问题。 没有二极管,如矩阵中某个矩形三个顶点同时导通,就无法判断矩形中第四个顶点的状态 学习了。
页:
[1]