非阻塞按键-基于定时器获取延时

static inline uint8_t elapsed_ge(uint16_t start, uint16_t delay)
{
    uint16_t now = TIM10NOW;
    return (uint16_t)(now - start) >= delay;
}
typedef struct {
    uint8_t stable;        // 去抖后的稳定状态(0/1)
    uint8_t last_raw;      // 上一次采样的原始状态
    uint8_t debouncing;    // 是否正在去抖
    uint16_t t0;           // 去抖开始时间
} KeyDebounce_t;
#define DEBOUNCE_TICKS  (20u * 2u)   // 例:20ms,若 500us/tick => 1ms=2tick

uint8_t Key_Update(KeyDebounce_t *k)
{
    uint8_t raw = KEY_READ();  // 当前原始电平/状态
    uint8_t event = 0;

    // 1) 检测到原始输入变化:启动去抖计时
    if (!k->debouncing) {
        if (raw != k->stable) {
            k->debouncing = 1;
            k->t0 = TIM10NOW;
            k->last_raw = raw;
        }
        return 0;
    }

    // 2) 去抖期间,如果又变了:重新计时(说明还在抖)
    if (raw != k->last_raw) {
        k->last_raw = raw;
        k->t0 = TIM10NOW;
        return 0;
    }

    // 3) 原始输入保持不变满 debounce 时间:确认稳定改变
    if (elapsed_ge(k->t0, DEBOUNCE_TICKS)) {
        k->debouncing = 0;

        // 此时 raw 持续稳定,更新 stable
        if (k->stable != raw) {
            k->stable = raw;

            // 产生事件:例如 stable 变成“按下电平”
            if (k->stable == KEY_PRESSED_LEVEL) {
                event = 1; // 按下事件
            }
        }
    }

    return event;
}
posted @ 2026-01-30 22:31  xs314  阅读(4)  评论(0)    收藏  举报