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
相关产品推荐
相关产品推荐

