You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nucleo板Mbed平台多输入Switch密码锁故障排查求助

密码锁代码问题排查与修复

核心问题分析

1. 位掩码逻辑完全倒置

代码中SW1的状态判断与其他按键逻辑矛盾:

int Inputs = (SW1==0) << 0 | (SW2==1) << 1 | (SW3==1) << 2 | (SW4==1) << 3 | (SW5==1) << 4;
  • 前置代码while (SW1==0)表明SW1按下时状态为1,松开时为0,但此处用SW1==0生成位0,导致:
    • SW1松开时位0为1,按下时位0为0
  • 其他按键以SWx==1生成对应位,按下时该位为1,松开时为0
  • 最终只有按下SW1且其他按键松开时,Inputs才会等于0,恰好触发case 0,与你描述的现象完全匹配。

2. 未实现序列检测逻辑

需求是检测按顺序按下并释放的按键序列(SW1 → SW2 → SW5 → SW3+SW4 → SW2+SW3),但你的代码仅一次性读取当前所有按键状态,未跟踪序列步骤,完全不符合功能要求。

3. 缺少按键消抖

按键按下/松开时会产生机械抖动,直接读取状态会导致误判,必须添加消抖延迟。

4. 代码语法不完整

  • switch语句缺少闭合的}
  • case 6未添加break语句
  • 主循环逻辑执行一次后未正确回到等待状态

修复后的完整代码示例

以下代码修正了逻辑错误、添加消抖机制、实现了序列检测功能:

// 按键输入对象
DigitalIn SW1(USER_BUTTON);
DigitalIn SW2(BTN1_PIN);
DigitalIn SW3(BTN2_PIN);
DigitalInOut SW4(BTN3_PIN, PIN_INPUT, PullDown, 0);
DigitalInOut SW5(BTN4_PIN, PIN_INPUT, PullDown, 0);

// LED控制(顺序:红、黄、绿)
BusOut leds(TRAF_RED1_PIN, TRAF_YEL1_PIN, TRAF_GRN1_PIN);

// 蜂鸣器
Buzzer alarm;

// 消抖延迟(单位:微秒)
const int DEBOUNCE_DELAY = 50000;

// 等待按键按下并消抖
bool wait_for_press(DigitalIn& btn) {
    while (btn == 0);
    wait_us(DEBOUNCE_DELAY);
    return btn == 1;
}

// 等待按键松开并消抖
bool wait_for_release(DigitalIn& btn) {
    while (btn == 1);
    wait_us(DEBOUNCE_DELAY);
    return btn == 0;
}

// 等待两个按键同时按下并消抖
bool wait_for_double_press(DigitalIn& btn1, DigitalIn& btn2) {
    while (!(btn1 == 1 && btn2 == 1));
    wait_us(DEBOUNCE_DELAY);
    return (btn1 == 1 && btn2 == 1);
}

int main()
{
    leds = 0;
    while (true)
    {
        // 初始提示音
        alarm.playTone("A", Buzzer::HIGHER_OCTAVE);
        wait_us(250000);
        alarm.rest();
        leds = 0;

        printf("请输入密码序列\n");

        // 步骤1:SW1按下并松开
        if (!wait_for_press(SW1) || !wait_for_release(SW1)) goto error_state;
        printf("步骤1正确\n");

        // 步骤2:SW2按下并松开
        if (!wait_for_press(SW2) || !wait_for_release(SW2)) goto error_state;
        printf("步骤2正确\n");

        // 步骤3:SW5按下并松开
        if (!wait_for_press(SW5) || !wait_for_release(SW5)) goto error_state;
        printf("步骤3正确\n");

        // 步骤4:SW3+SW4同时按下并松开
        if (!wait_for_double_press(SW3, SW4)) goto error_state;
        wait_for_release(SW3);
        wait_for_release(SW4);
        printf("步骤4正确\n");

        // 步骤5:SW2+SW3同时按下并松开
        if (!wait_for_double_press(SW2, SW3)) goto error_state;
        wait_for_release(SW2);
        wait_for_release(SW3);

        // 序列正确:绿灯闪烁3次
        printf("密码正确!\n");
        for (int i = 0; i < 3; i++) {
            leds = 1; // 001对应绿灯
            wait_us(1000000);
            leds = 0;
            wait_us(1000000);
        }
        continue;

    error_state:
        // 错误状态:红灯亮+蜂鸣5秒
        printf("密码错误!\n");
        leds = 4; // 100对应红灯
        alarm.playTone("A", Buzzer::HIGHER_OCTAVE);
        wait_us(5000000);
        alarm.rest();
        leds = 0;
    }
}

替代实现思路(无需switch)

密码锁本质是时间序列检测,switch仅适合处理单一时刻的状态组合,更合适的方案是用状态机跟踪步骤:

  • 将密码拆分为独立步骤,每一步只检测当前需要的按键动作
  • 用函数封装按键检测逻辑(按下、松开、同时按下),避免代码冗余
  • 任何步骤出错直接跳转到错误处理分支

内容的提问来源于stack exchange,提问作者DakarusJoe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 02:15:39