Files
health-wellness-device-2/include/button_manager.h

75 lines
2.3 KiB
C++
Raw Permalink 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.
/**
* @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