四汐 发表于 5 天前

8 x 8 (或A x B?) 矩阵按键 按键处理 单击或长按?

<h1>8 x 8 (或A x B?) 矩阵按键 按键处理 单击&amp;长按</h1>
<p><em><strong>目录:</strong></em><a href="https://www.stcaimcu.com/thread-17182-1-1.html"><em><strong>【虹星宝典】记录单片机学习之旅——目录</strong></em></a></p>
<p><strong>注:从本例程起,使用USB-CDC模式进行程序下载。</strong></p>
<h2>矩阵按键原理</h2>
<p><img src="data/attachment/forum/202504/27/223702e116j41mok14oo0r.png" alt="image.png" title="image.png" /></p>
<p><strong>以这个8x8的矩阵按键为例:</strong></p>
<p><img src="data/attachment/forum/202504/27/223713boc6h16hk9nouhcy.png" alt="image.png" title="image.png" /></p>
<h3>如何实现64个按键的扫描?</h3>
<p><strong>试想一下,当我们给KA通电时,对K1-K8的状态进行读取,如果有按键按下,那么对应的端口就会由低电平变成高电平,由此即可判断哪一个按键按下了。</strong></p>
<p><strong>如此反复对K1-KH端口置高电平,读取K1-K8端口的状态,便可以实现8x8矩阵按键的扫描,一般会对置高电平的端口配置为推挽输出模式,对读取的端口设置为高阻输入+下拉的模式。</strong></p>
<p><strong>如此便可写一个扫描按键是否按下的函数,对与N x N的矩阵按键原理也是大同小异的。</strong></p>
<p><img src="data/attachment/forum/202504/27/223722cbcy4fd25injjfcc.png" alt="image.png" title="image.png" /></p>
<p><img src="data/attachment/forum/202504/27/223728pdsds7giii0we47e.png" alt="image.png" title="image.png" /></p>
<h3>如何实现按键状态的判断?</h3>
<p><strong>一般的,按键分为 ”未按下“ ”消抖“ ”单击“ ”长按“等多种状态,为了更好的区分当按键按下时处于什么状态,确定一个时基便十分重要了,例如我以10ms为一次扫描时间间隔基准,即每10ms扫描一次按键状态,并保存这个按键按下的时长,通过判断按下的时长,即可推断出按键为何种状态。</strong></p>
<p><strong>案例中以按下到松开的时长在2s内时,判断为单击动作。按下超过2s时,判断为长按动作。</strong></p>
<p><img src="data/attachment/forum/202504/27/223739ltzjwjzje4erlkzn.png" alt="image.png" title="image.png" /></p>
<h2>实例展示(仅展示部分代码)</h2>
<p><strong>这里以10ms作为扫描时基,如果A1为单击操作则打印“A1 Press!”,其他按键同理。</strong></p>
<p><img src="data/attachment/forum/202504/27/223748yh226elm16xea62l.png" alt="image.png" title="image.png" /></p>
<p><strong>演示视频:</strong></p>
<video controls="controls" src="forum.php?mod=attachment&amp;aid=95907"></video>

四汐 发表于 5 天前





2025-04-29:
推出支持自定义行列引脚模式的矩阵按键扫描函数,真正实现任意AxB行列式矩阵按键扫描
欢迎小伙伴们体验测试


国芯人工智能 发表于 5 天前

矩阵按键扫描与状态判断的实现

矩阵按键扫描原理

在嵌入式系统中,矩阵按键是一种常见的输入设备,通过减少I/O引脚的使用数量,实现多按键的检测。以8x8矩阵按键为例,其基本原理如下:

1. 硬件连接:矩阵按键通常由行和列组成,例如8行8列共64个按键。每一行和每一列分别连接到微控制器的I/O引脚。

2. 扫描方法:
行扫描:将某一行置为高电平(推挽输出模式),其余行置为低电平。
列检测:读取每一列的状态(高阻输入+下拉模式)。如果某一列检测到高电平,说明该列与当前行的交叉点有按键按下。
循环扫描:依次对每一行进行上述操作,完成整个矩阵的扫描。

3. 状态判断:
消抖处理:按键在按下和释放时可能会产生抖动,需要通过软件消抖算法来消除抖动影响。
时基确定:以10ms为扫描间隔,记录按键按下的时长。
状态分类:根据按下的时长,将按键状态分为“未按下”、“消抖”、“单击”和“长按”等。

按键状态判断的实现

1. 时基与扫描:
以10ms为时基,每隔10ms进行一次按键扫描。
记录每个按键按下的时长,通过判断时长来区分不同的按键状态。

2. 状态分类:
单击:按键按下到松开的时长在2秒内。
长按:按键按下超过2秒。

实例代码展示

以下是一个简化的按键扫描与状态判断的代码示例:

c
include
include
include

define ROWS 8
define COLS 8
define DEBOUNCETIME 20 // 消抖时间20ms
define LONGPRESSTIME 2000 // 长按时间2000ms

uint8t keymatrix = {0}; // 按键矩阵状态
uint16t keypresstime = {0}; // 按键按下时长

void scankeys() {
    static uint16t debouncecounter = {0};
    for (uint8t row = 0; row < ROWS; row++) {
      // 设置当前行为高电平
      setrowhigh(row);
      for (uint8t col = 0; col < COLS; col++) {
            // 读取列状态
            bool keystate = readcol(col);
            if (keystate) {
                if (debouncecounter < DEBOUNCETIME) {
                  debouncecounter++;
                } else {
                  keypresstime++;
                }
            } else {
                if (debouncecounter > 0) {
                  debouncecounter--;
                } else {
                  if (keypresstime > 0) {
                        if (keypresstime < LONGPRESSTIME) {
                            printf("Key [%d][%d] Press!\n", row, col);
                        } else {
                            printf("Key [%d][%d] Long Press!\n", row, col);
                        }
                        keypresstime = 0;
                  }
                }
            }
      }
      // 恢复当前行为低电平
      setrowlow(row);
    }
}

int main() {
    while (1) {
      scankeys();
      delayms(10); // 10ms时基
    }
    return 0;
}

总结

通过上述方法,可以实现对8x8矩阵按键的扫描与状态判断。关键在于合理设置时基、消抖处理以及按键状态的分类。这种方法同样适用于其他规模的矩阵按键,只需调整行和列的数量即可。在实际应用中,还需根据具体硬件和需求进行优化和调整。

[本文内容由国芯人工智能辅助生成,仅供参考]
页: [1]
查看完整版本: 8 x 8 (或A x B?) 矩阵按键 按键处理 单击或长按?