记录一个“诡异”的矩阵键盘问题-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 1427|回复: 1

记录一个“诡异”的矩阵键盘问题

[复制链接]
发表于 2021-10-27 09:40 | 显示全部楼层 |阅读模式
最近用船型开关做了一个矩阵键盘,电路图如下:
key1.png
简单的说就是 KEY_ROW1-3 轮流为 HIGH 然后通过读取 KEY_COL1 引脚的电平就能得到当前开关状态。编写的取得按键信息的代码如下:
int GetPressed() {
  int result = 0;
  
digitalWrite(KEY_ROW1, HIGH);
digitalWrite(KEY_ROW2, LOW);
digitalWrite(KEY_ROW3, LOW);
  // Upper line
  result =(digitalRead(KEY_COL1) << 3) +
          (digitalRead(KEY_COL2) << 2) +
          (digitalRead(KEY_COL3) << 1) +
          digitalRead(KEY_COL4);
  // Middle line
digitalWrite(KEY_ROW1, LOW);
digitalWrite(KEY_ROW2, HIGH);
digitalWrite(KEY_ROW3, LOW);
  result =((digitalRead(KEY_COL1) << 3) +
           (digitalRead(KEY_COL2) << 2) +
           (digitalRead(KEY_COL3) << 1) +
           (digitalRead(KEY_COL4))) +
           result *10;
  
  
  // Buttom line
  digitalWrite(KEY_ROW1,LOW);
digitalWrite(KEY_ROW2, LOW);
digitalWrite(KEY_ROW3, HIGH);
  result =(digitalRead(KEY_COL1) << 3) +
          (digitalRead(KEY_COL2) << 2) +
          (digitalRead(KEY_COL3) << 1) +
          (digitalRead(KEY_COL4) << 0) +
           result *10;
  return result;
}
调试中我惊奇的发现每次读取KEY_COL1的值竟然不同,示意如下:

key2.jpg
即使我将digitalRead直接写成(GPIO.in>> KEY_COL1) & 0x1 也有同样的现象。
于是针对这个问题做了如下实验:
1.     直接在 FireBeetle上跑,不插入在矩阵键盘中,无现象;
2.     将 x 定义为全局变量,同样现象;
3.     试图关掉ESP32的编译优化功能,没有找到对应项目
1的结果判断这个问题和我的硬件是有关的,最终拿出了示波器,果真,上了之后能够看到如下波形(黄色是KEY_COL1,绿色是KEY_ROW1):可以看到当拉高之后接收端马上变高,但是拉低之后过了很久才会降低。于是怀疑的点就是读取太快,上一个拉高的影响还没有完全结束,导致了误判。

key3.png

有了上面的猜想就编写一个代码,不断拉高ROW1 ROW3 ,然后看看是否会出现这样的问题,结果显示:如果一个 ROW上有一个按键是闭合的,那么另外一个 ROW的读取很大概率产生误判。
digitalWrite(KEY_ROW1, HIGH);
  digitalWrite(KEY_ROW2,LOW);
digitalWrite(KEY_ROW3,  LOW);
c1=(digitalRead(KEY_COL1) << 3) +
          (digitalRead(KEY_COL2) << 2) +
          (digitalRead(KEY_COL3) << 1) +
          digitalRead(KEY_COL4);
digitalWrite(KEY_ROW1, LOW);
  digitalWrite(KEY_ROW2,LOW);
digitalWrite(KEY_ROW3,  HIGH);
c2=(digitalRead(KEY_COL1) << 3) +
          (digitalRead(KEY_COL2) << 2) +
          (digitalRead(KEY_COL3) << 1) +
          digitalRead(KEY_COL4);
if (c1==c2){Serial.print(c1);Serial.print("  ");Serial.println(c2);delay(1000);}

key4.png

下面黄色是KEY_COL1Pin (读取)和KEY_ROW3(发送)的波形图(我的示波器只有两个通道),可以看到ROW1拉高的影响持续了到KEY_ROW3的发生,因此再次读取 KEY_COL1的结果是错误的。

key5.png

找到了原因问题就好解决了,每次 digitalRead() 之后加一个一个delay 让它完成放电就能保证结果的正确性了。

有诗为证:

矩阵键盘惹人愁,
现象诡异结果谬。
I/O 若水不停歇,
CPU更快似光流。


发表于 2021-10-27 11:46 | 显示全部楼层
可以套个millis(),连消抖都一起搞定
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 09:43 , Processed in 0.116029 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表