75 lines
2.3 KiB
C++
75 lines
2.3 KiB
C++
/**
|
||
* @file button_manager.h
|
||
* @brief 三按钮管理器 - 双向去抖 + 长按/短按识别 + 超时自愈
|
||
*
|
||
* 按钮1 (GPIO14): 长按1.5秒 → 配网
|
||
* 按钮2 (GPIO13): 短按 → 解除报警
|
||
* 按钮3 (GPIO46): 短按 → 翻页
|
||
*
|
||
* 去抖策略: 状态变化需持续稳定 BTN_DEBOUNCE_MS 才确认
|
||
* 自愈策略: 按钮按下超过 10 秒强制复位,防止卡死
|
||
*/
|
||
|
||
#ifndef BUTTON_MANAGER_H
|
||
#define BUTTON_MANAGER_H
|
||
|
||
#include <Arduino.h>
|
||
#include "config.h"
|
||
|
||
#define BTN_STUCK_TIMEOUT_MS 10000 // 按钮卡死超时 (10秒强制复位)
|
||
|
||
typedef void (*ButtonCallback)(void);
|
||
|
||
class ButtonManager {
|
||
public:
|
||
ButtonManager();
|
||
|
||
/** 初始化三个按钮引脚 */
|
||
void begin();
|
||
|
||
/** 主循环轮询 (每 10ms 调用) */
|
||
void loop();
|
||
|
||
/** 注册回调 */
|
||
void onProvisionLongPress(ButtonCallback cb) { _cbProvision = cb; }
|
||
void onAlarmDismiss(ButtonCallback cb) { _cbDismiss = cb; }
|
||
void onPageSwitch(ButtonCallback cb) { _cbPage = cb; }
|
||
|
||
private:
|
||
/**
|
||
* 按钮状态机 (基于稳定读数而非边沿)
|
||
*
|
||
* 状态转换:
|
||
* IDLE ──[raw稳定LOW×BTN_DEBOUNCE_MS]──→ PRESSED (记录pressTime)
|
||
* PRESSED ──[hold≥BTN_LONG_PRESS_MS]──→ 触发长按回调 (仅限hasLong)
|
||
* PRESSED ──[raw稳定HIGH×BTN_DEBOUNCE_MS]──→ 检查hold时长触发短按 → IDLE
|
||
* PRESSED ──[hold≥BTN_STUCK_TIMEOUT_MS]──→ 强制复位 → IDLE (防卡死)
|
||
*/
|
||
struct ButtonState {
|
||
uint8_t pin;
|
||
bool stableState; // 当前确认的稳定状态 (true=按下)
|
||
bool rawState; // 上一次 raw 读值
|
||
uint32_t changeTime; // raw 状态变化时刻
|
||
uint32_t pressTime; // 稳定按下时刻 (ms)
|
||
bool longTriggered; // 长按已触发
|
||
bool shortPending; // 等待释放以判定短按
|
||
};
|
||
|
||
/** 处理单个按钮 (基于稳定状态而非瞬时边沿) */
|
||
void _processButton(ButtonState& btn, bool hasShort, bool hasLong);
|
||
bool _readPin(uint8_t pin);
|
||
|
||
/** 强制复位单个按钮 */
|
||
void _resetButton(ButtonState& btn);
|
||
|
||
ButtonState _btnProvision;
|
||
ButtonState _btnDismiss;
|
||
ButtonState _btnPage;
|
||
|
||
ButtonCallback _cbProvision;
|
||
ButtonCallback _cbDismiss;
|
||
ButtonCallback _cbPage;
|
||
};
|
||
|
||
#endif // BUTTON_MANAGER_H
|