2026-07-09 10:49:15 +08:00
|
|
|
|
# 编码实现 - 按键扫描与事件判定 (Docs/60_coding/mod-key.md)
|
2026-07-09 10:31:36 +08:00
|
|
|
|
|
2026-07-09 17:42:55 +08:00
|
|
|
|
本文件对应按键状态消抖、确认键长按 3 秒判定以及主键事件注入的具体编码实现细节。
|
2026-07-09 10:31:36 +08:00
|
|
|
|
|
|
|
|
|
|
## 1. 对应代码源文件
|
|
|
|
|
|
|
2026-07-09 17:42:55 +08:00
|
|
|
|
* [App/main.c](file:///c:/workfile/105/stc32g12k128/App/main.c) (定时中断内的按键扫描、按键状态高阻读取、长短按电平扫描)
|
2026-07-09 10:31:36 +08:00
|
|
|
|
|
|
|
|
|
|
## 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;
|
2026-07-09 10:49:15 +08:00
|
|
|
|
static u8 key_confirm_state = 0xFF;
|
|
|
|
|
|
static u8 key_sos1_state = 0xFF;
|
|
|
|
|
|
static u8 key_sos2_state = 0xFF;
|
|
|
|
|
|
u8 key_sos_state;
|
2026-07-09 10:31:36 +08:00
|
|
|
|
|
|
|
|
|
|
key_up_state = (key_up_state << 1) | KEY_UP;
|
|
|
|
|
|
key_down_state = (key_down_state << 1) | KEY_DOWN;
|
2026-07-09 10:49:15 +08:00
|
|
|
|
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;
|
|
|
|
|
|
|
2026-07-09 17:42:55 +08:00
|
|
|
|
// 双上部 SOS 键的逻辑并联
|
2026-07-09 10:49:15 +08:00
|
|
|
|
key_sos_state = key_sos1_state & key_sos2_state;
|
2026-07-09 10:31:36 +08:00
|
|
|
|
|
2026-07-09 17:42:55 +08:00
|
|
|
|
// 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;
|
2026-07-09 10:31:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2026-07-09 17:42:55 +08:00
|
|
|
|
if (key_down_hold > 2 && key_down_hold < 200) {
|
|
|
|
|
|
key_event_buf = KEY_DOWN_SHORT;
|
2026-07-09 10:31:36 +08:00
|
|
|
|
}
|
2026-07-09 17:42:55 +08:00
|
|
|
|
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;
|
2026-07-09 10:49:15 +08:00
|
|
|
|
}
|
2026-07-09 17:42:55 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
if (key_confirm_hold > 2 && key_confirm_hold < 300) {
|
|
|
|
|
|
key_event_buf = KEY_CONFIRM_CLICK;
|
2026-07-09 10:31:36 +08:00
|
|
|
|
}
|
2026-07-09 17:42:55 +08:00
|
|
|
|
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;
|
2026-07-09 10:31:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-07-09 17:45:35 +08:00
|
|
|
|
### 2.2 事件解调与微调分配分发 (Process_System_Event 示例)
|
2026-07-09 17:42:55 +08:00
|
|
|
|
在主循环事件分发中,对各个状态下的事件进行处理:
|
2026-07-09 10:31:36 +08:00
|
|
|
|
```c
|
2026-07-09 17:42:55 +08:00
|
|
|
|
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) {
|
|
|
|
|
|
current_state = STATE_CLOCK;
|
|
|
|
|
|
Redraw = 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case STATE_PAIR_CONFIRM:
|
2026-07-09 17:45:35 +08:00
|
|
|
|
// 直接进行后缀序号微调 (传感器类型已由射频数据码自动识别并锁定)
|
|
|
|
|
|
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) {
|
|
|
|
|
|
// 点击 CONFIRM,直接将自动解析的类型和调整好的序号写入数据库
|
|
|
|
|
|
Add_Sensor(captured_addr, auto_detected_type, selected_suffix);
|
|
|
|
|
|
current_state = STATE_CLOCK;
|
|
|
|
|
|
Redraw = 1;
|
|
|
|
|
|
} else if (evt == KEY_CONFIRM_LONG) {
|
|
|
|
|
|
// 长按 3 秒放弃保存返回时钟
|
2026-07-09 17:42:55 +08:00
|
|
|
|
current_state = STATE_CLOCK;
|
|
|
|
|
|
Redraw = 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case STATE_IPC_BIND:
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
|
|
// 其它状态处理...
|
|
|
|
|
|
}
|
2026-07-09 10:31:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
```
|
2026-07-09 17:42:55 +08:00
|
|
|
|
|
|
|
|
|
|
<!-- Checked and verified with SGM3833 boost/inverting PMIC removal and LCD_PWR_CTRL update changes V2 -->
|