8 x 8 (或A x B?) 矩阵按键 按键处理 单击或长按?
<h1>8 x 8 (或A x B?) 矩阵按键 按键处理 单击&长按</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&aid=95907"></video>
2025-04-29:
推出支持自定义行列引脚模式的矩阵按键扫描函数,真正实现任意AxB行列式矩阵按键扫描
欢迎小伙伴们体验测试
矩阵按键扫描与状态判断的实现
矩阵按键扫描原理
在嵌入式系统中,矩阵按键是一种常见的输入设备,通过减少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矩阵按键的扫描与状态判断。关键在于合理设置时基、消抖处理以及按键状态的分类。这种方法同样适用于其他规模的矩阵按键,只需调整行和列的数量即可。在实际应用中,还需根据具体硬件和需求进行优化和调整。
[本文内容由国芯人工智能辅助生成,仅供参考] https://www.stcaimcu.com/thread-19608-1-1.html
大佬,如果是我这种矩阵按键,我应该修改哪些部分的代码{:4_187:} 四汐 发表于 2025-4-27 23:12
2025-04-29:
推出支持自定义行列引脚模式的矩阵按键扫描函数,真正实现任意AxB行列式矩阵按键扫描
欢 ...
你好,请问附件 4-Key(AxB) 支持 单键短按长按,组合键最多支持3键最长5秒 的功能吗?我用的原理如图
另代码中行是下拉的,跟注释不一样
/**
* @name GPIO_Key_Init
* @brief 矩阵按键GPIO口初始化
* @version 版本:v1.0
* @date 日期:2025-04-22
* @author 作者:四汐
* @note 注释:行设置为上拉,列设置为下拉。行置1时,读列
*/
void GPIO_Key_Init(void)
{
// P2 列 ABCDEFGH 推挽输出
P2M0 = 0xff; P2M1 = 0x00;
// P2PU = 0xff;
P2PD = 0xff;
// P0 行 12345678 高阻输入 下拉
P0M0 = 0x00; P0M1 = 0xff;
P0PD = 0xff;
}
我移植试了下,好像不能组合键
mfsljtpq 发表于 2025-9-25 15:23
你好,请问附件 4-Key(AxB) 支持 单键短按长按,组合键最多支持3键最长5秒 的功能吗?我用的原理如图
你的程序无法下载。
这个注释应该是忘记改了。按照实际代码来。
行和列的定义其实不重要,重要是明白哪些是【读取】口,哪些是【扫描】口。
【读取】设置为高阻输入,配置成下拉,默认为低电平,即没有按下。
【扫描】设置为推挽输出,配置成下拉,按下按键时,两个下拉电阻相当于并联,影响不大;配置成上拉,按下按键时,上拉和下拉电阻相当于串联在电源两端,【读取】口的电平就是VCC的一半左右。我之前应该是做了测试,认为配置下拉更稳定。
矩阵按键的原理就是:
在一个时刻内,【扫描A】输出高电平,其余【扫描X】输出低电平,同时检测【读取1-Y】的电平,如果检测【读取1】是高电平,那么认为A1按下,再通过算法实现“消抖”、“单击”等。
你的串口数据,看起来像是【读取】口配置成上拉了,就会判断按键一直按着,然后判断成“长按”了。 四汐 发表于 2025-9-26 10:12
你的程序无法下载。
这个注释应该是忘记改了。按照实际代码来。
行和列的定义其实不重要,重要是明白哪些 ...昨天打印错误是因为一个口配置错了,更改后可以单键短按和长按了。
用你的软硬件支持最大3个键组合键最长5秒的功能吗?
页:
[1]