Files
stc32g128k/Docs/60_coding/mod-key.md

93 lines
3.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 编码实现 - 按键扫描与事件判定 (Docs/60_coding/mod-key.md)
本文件对应按键状态消抖、长按计时判定以及组合按键识别的具体编码实现细节。
## 1. 对应代码源文件
* [App/main.c](file:///c:/workfile/105/stc32g12k128/App/main.c) (定时中断内的按键扫描、按键状态累加、主循环事件处理)
## 2. 关键代码片段与逻辑实现
### 2.1 按键中断定时器扫描 (每 10ms 调度一次)
`Timer1_Isr` (1ms 滴答) 内,通过 `key_scan_timer` 进行 10ms 分频并调用 `Key_Scan_Process()`
```c
void Key_Scan_Process(void) {
// 1. 读取引脚状态并消抖
static u8 key_up_state = 0xFF;
static u8 key_down_state = 0xFF;
static u8 key_confirm_state = 0xFF;
static u8 key_sos1_state = 0xFF;
static u8 key_sos2_state = 0xFF;
u8 key_sos_state;
key_up_state = (key_up_state << 1) | KEY_UP;
key_down_state = (key_down_state << 1) | KEY_DOWN;
key_confirm_state = (key_confirm_state << 1) | KEY_CONFIRM;
key_sos1_state = (key_sos1_state << 1) | KEY_SOS1;
key_sos2_state = (key_sos2_state << 1) | KEY_SOS2;
// 双上部 SOS 键的逻辑并联(低电平有效,按位与运算相当于逻辑或)
key_sos_state = key_sos1_state & key_sos2_state;
// 2. 长按与组合按键计时器累加
if ((key_up_state & 0x07) == 0 && (key_down_state & 0x07) == 0) {
// ▲ + ▼ 组合键按住
comb_hold++;
if (comb_hold == 300) { // 3秒
key_event_buf = KEY_COMB_LONG;
}
} else {
comb_hold = 0;
// 单个按键:▲ 键 (UP)
if ((key_up_state & 0x07) == 0) {
key_up_hold++;
} else {
if (key_up_hold > 2 && key_up_hold < 200) {
key_event_buf = KEY_UP_SHORT;
}
key_up_hold = 0;
}
// 单个按键:■ 确认键 (CONFIRM)
if ((key_confirm_state & 0x07) == 0) {
key_confirm_hold++;
} else {
if (key_confirm_hold > 2 && key_confirm_hold < 200) {
key_event_buf = KEY_CONFIRM_CLICK;
}
key_confirm_hold = 0;
}
// 单个按键:并联 SOS 键
if ((key_sos_state & 0x07) == 0) {
key_sos_hold++;
if (key_sos_hold == 500) { // 5秒
key_event_buf = KEY_SOS_LONG;
}
} else {
if (key_sos_hold > 2 && key_sos_hold < 500) {
key_event_buf = KEY_SOS_SHORT;
}
key_sos_hold = 0;
}
// ▼ 键 (DOWN) 处理同上...
}
}
```
<!-- Checked and verified with always-on screen and sleep removal changes -->
### 2.2 事件异步读取与清除
主循环在其周期内轮询 `key_event_buf`。一旦发现其非 `KEY_EVENT_NONE`,拷贝并立即重置该缓冲区为 `KEY_EVENT_NONE` 以防止重复触发:
```c
if (key_event_buf != KEY_EVENT_NONE) {
KeyEvent evt = key_event_buf;
key_event_buf = KEY_EVENT_NONE; // 清空事件缓冲区
// 执行具体事件动作,如在常态下短按 SOS 进入 SOS 警报发射状态等
// ...
}
```
通过该缓冲区实现了按键中断采集与主循环处理的解耦。