docs: optimize SOS button behavior, add 2-step pairing wizard, and IPC exit action
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
# 编码实现 - 按键扫描与事件判定 (Docs/60_coding/mod-key.md)
|
||||
|
||||
本文件对应按键状态消抖、长按计时判定以及组合按键识别的具体编码实现细节。
|
||||
本文件对应按键状态消抖、确认键长按 3 秒判定以及主键事件注入的具体编码实现细节。
|
||||
|
||||
## 1. 对应代码源文件
|
||||
|
||||
* [App/main.c](file:///c:/workfile/105/stc32g12k128/App/main.c) (定时中断内的按键扫描、按键状态累加、主循环事件处理)
|
||||
* [App/main.c](file:///c:/workfile/105/stc32g12k128/App/main.c) (定时中断内的按键扫描、按键状态高阻读取、长短按电平扫描)
|
||||
|
||||
## 2. 关键代码片段与逻辑实现
|
||||
|
||||
@@ -26,67 +26,134 @@ void Key_Scan_Process(void) {
|
||||
key_sos1_state = (key_sos1_state << 1) | KEY_SOS1;
|
||||
key_sos2_state = (key_sos2_state << 1) | KEY_SOS2;
|
||||
|
||||
// 双上部 SOS 键的逻辑并联(低电平有效,按位与运算相当于逻辑或)
|
||||
// 双上部 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;
|
||||
// 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 {
|
||||
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;
|
||||
if (key_down_hold > 2 && key_down_hold < 200) {
|
||||
key_event_buf = KEY_DOWN_SHORT;
|
||||
}
|
||||
|
||||
// 单个按键:■ 确认键 (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;
|
||||
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;
|
||||
}
|
||||
|
||||
// 单个按键:并联 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;
|
||||
} else {
|
||||
if (key_confirm_hold > 2 && key_confirm_hold < 300) {
|
||||
key_event_buf = KEY_CONFIRM_CLICK;
|
||||
}
|
||||
// ▼ 键 (DOWN) 处理同上...
|
||||
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;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- Checked and verified with SGM3833 boost/inverting PMIC removal and LCD_PWR_CTRL update changes -->
|
||||
|
||||
### 2.2 事件异步读取与清除
|
||||
主循环在其周期内轮询 `key_event_buf`。一旦发现其非 `KEY_EVENT_NONE`,拷贝并立即重置该缓冲区为 `KEY_EVENT_NONE` 以防止重复触发:
|
||||
### 2.2 事件异步处理与分发 (Process_System_Event 示例)
|
||||
在主循环事件分发中,对各个状态下的事件进行处理:
|
||||
```c
|
||||
if (key_event_buf != KEY_EVENT_NONE) {
|
||||
KeyEvent evt = key_event_buf;
|
||||
key_event_buf = KEY_EVENT_NONE; // 清空事件缓冲区
|
||||
|
||||
// 执行具体事件动作,如在常态下短按 SOS 进入 SOS 警报发射状态等
|
||||
// ...
|
||||
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 -->
|
||||
|
||||
Reference in New Issue
Block a user