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

160 lines
5.5 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)
本文件对应按键状态消抖、确认键长按 3 秒判定以及主键事件注入的具体编码实现细节。
## 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. 按键长按与短按状态机扫描
// ▲ 键 (UP) 处理
if ((key_up_state & 0x07) == 0) {
key_up_hold++;
} else {
if (key_up_hold > 2) {
key_event_buf = KEY_UP_SHORT;
}
key_up_hold = 0;
}
// ▼ 键 (DOWN) 处理 (支持长按 2 秒清除报警/退出)
if ((key_down_state & 0x07) == 0) {
key_down_hold++;
if (key_down_hold == 200) { // 2秒
key_event_buf = KEY_DOWN_LONG;
}
} else {
if (key_down_hold > 2 && key_down_hold < 200) {
key_event_buf = KEY_DOWN_SHORT;
}
key_down_hold = 0;
}
// ■ 确认键 (CONFIRM) 处理 (支持长按 3 秒进入/退出)
if ((key_confirm_state & 0x07) == 0) {
key_confirm_hold++;
if (key_confirm_hold == 300) { // 3秒
key_event_buf = KEY_CONFIRM_LONG;
}
} else {
if (key_confirm_hold > 2 && key_confirm_hold < 300) {
key_event_buf = KEY_CONFIRM_CLICK;
}
key_confirm_hold = 0;
}
// 并联 SOS 键
if ((key_sos_state & 0x07) == 0) {
key_sos_hold++;
if (key_sos_hold == 3) {
key_event_buf = KEY_SOS_ACTIVE;
}
} else {
key_sos_hold = 0;
}
}
```
### 2.2 事件异步处理与分发 (Process_System_Event 示例)
在主循环事件分发中,对各个状态下的事件进行处理:
```c
void Process_System_Event(KeyEvent evt) {
switch (current_state) {
case STATE_MENU:
if (evt == KEY_UP_SHORT) {
// 菜单滚动
if (menu_index > 0) menu_index--;
Redraw = 1;
} else if (evt == KEY_DOWN_SHORT) {
if (menu_index < 3) menu_index++;
Redraw = 1;
} else if (evt == KEY_CONFIRM_CLICK) {
// 点击确认进入选中分支
Enter_Menu_Branch(menu_index);
} else if (evt == KEY_CONFIRM_LONG) {
// 长按 3 秒退出菜单返回时钟待机
current_state = STATE_CLOCK;
Redraw = 1;
}
break;
case STATE_PAIR_CONFIRM:
if (confirm_edit_focus == 0) {
// 第一步:编辑传感器类型
if (evt == KEY_UP_SHORT) {
if (selected_type < 6) selected_type++;
else selected_type = 0;
Redraw = 1;
} else if (evt == KEY_DOWN_SHORT) {
if (selected_type > 0) selected_type--;
else selected_type = 6;
Redraw = 1;
} else if (evt == KEY_CONFIRM_CLICK) {
// 点击确认,锁定类型,跳入第二步选择序号
confirm_edit_focus = 1;
Redraw = 1;
}
} else if (confirm_edit_focus == 1) {
// 第二步:编辑序号后缀
if (evt == KEY_UP_SHORT) {
if (selected_suffix < 99) selected_suffix++;
Redraw = 1;
} else if (evt == KEY_DOWN_SHORT) {
if (selected_suffix > 1) selected_suffix--;
Redraw = 1;
} else if (evt == KEY_CONFIRM_CLICK) {
// 点击确认,完成最终写入保存,返回时钟
Add_Sensor(captured_addr, selected_type, selected_suffix);
current_state = STATE_CLOCK;
Redraw = 1;
}
}
// 长按 CONFIRM 3 秒退出不保存
if (evt == KEY_CONFIRM_LONG) {
current_state = STATE_CLOCK;
Redraw = 1;
}
break;
case STATE_IPC_BIND:
// IPC 绑定连发状态中支持物理长按退出
if (evt == KEY_CONFIRM_LONG || evt == KEY_DOWN_LONG) {
current_state = STATE_CLOCK;
Redraw = 1;
} else if (evt == KEY_CONFIRM_CLICK) {
// 重发绑定信号
EV1527_Transmit(bracelet_factory_id, 0x01);
}
break;
// 其它状态处理...
}
}
```
<!-- Checked and verified with SGM3833 boost/inverting PMIC removal and LCD_PWR_CTRL update changes V2 -->