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

Arduino test函数运行异常 按键后直接触发die函数问题排查

问题说明
  • 约束要求:循环逻辑不能依赖if函数实现判断分支
  • 故障现象:
    • 按下按键后,无论colour与light取何值,都会直接进入die()函数,生命值从2跳变为-1
    • 按键按下时,绝大多数场景下会重复执行test()函数,直到程序触发终止逻辑
  • 原有问题代码:
boolean test(void)
{
  if (light==0)
  {
     return false;
  }
  ;
  if ( BIT_IS_SET(PINB, 2) ) 
  {
    if ((colour==1 && light==4)||(colour==0 && light==5))
    {
       mark=mark+100;
       light=0;
       return true;
    }
    else
    {
      life=life-1;
      analogWrite(SPEAKERPIN,200);
      delay(10);
      analogWrite(SPEAKERPIN,0);
      light=0;
      return true;
    }
    ;
  }
  delay(10);
  if(BIT_IS_SET(PINB, 3)) 
  {
    if ((colour==1 && light==5)||(colour==0 && light==4))
    {
      mark=mark+100;
       light=0;
       return true;
    }
    else
    {
      life=life-1;
      analogWrite(SPEAKERPIN,200);
      delay(10);
      analogWrite(SPEAKERPIN,0);
      light=0;
      return true;
    }
  }
  return false;
}
void loop()
{
  game();
  while(test()==false)
  {
  }
  ;
  if(life<0)
  {
    die();
  }
}
故障根因
  1. 无按键锁存/释放检测逻辑:机械按键按下后会保持几十毫秒的有效触发电平,原代码检测到按键电平触发后,没有等待按键释放就返回。主循环loop会在按键保持按下的周期内反复执行game()→test()流程,每轮都触发一次扣血逻辑,初始2点生命值连续扣3次就会跳到-1,直接触发死亡逻辑。
  2. 分支逻辑冗余冲突:检测到PINB2按键触发后,无论匹配是否成功都会直接return true,后续的10ms消抖延时、PINB3按键检测逻辑永远不会执行,两个按键实际只有一个能生效。
  3. 循环判断依赖多层if嵌套:不符合需求的实现约束,多层嵌套也容易引入逻辑漏洞。
修复方案(无if依赖实现)

用位运算+三目运算符+状态查表替代所有循环内的if分支判断,同时增加按键释放等待逻辑,避免单次按键重复触发:

// 匹配状态查表:match_map[colour][light] = 1为按键匹配加分,0为不匹配扣血
const uint8_t match_map[2][6] = {
    [0] = {[4] = 0, [5] = 1}, // colour=0时,PB3对应light=4、PB2对应light=5
    [1] = {[4] = 1, [5] = 0}  // colour=1时,PB2对应light=4、PB3对应light=5
};
#define KEY_MASK ((1<<2)|(1<<3))

boolean test(void)
{
    // 三目运算替代if判断light状态
    return (light == 0) ? false : 
    // 位运算读取按键状态,非0代表有按键按下
    ((PINB & KEY_MASK) != 0) ? (
        // 10ms消抖
        delay(10),
        // 二次确认按键电平,位运算判断按下的键位
        uint8_t key = PINB & KEY_MASK,
        // 等待按键释放,避免重复触发
        while(PINB & KEY_MASK),
        // 查表判断当前按键与灯光、颜色是否匹配
        uint8_t is_match = (key == (1<<2)) ? match_map[colour][light] : match_map[colour][light] ^ 1,
        // 匹配加分/不匹配扣血+蜂鸣提示,用逗号表达式顺序执行
        is_match ? (mark += 100) : (
            life -=1,
            analogWrite(SPEAKERPIN,200),
            delay(10),
            analogWrite(SPEAKERPIN,0)
        ),
        // 复位灯光状态
        light = 0,
        true
    ) : false;
}

void loop()
{
    game();
    // 循环等待test返回true,无if嵌套
    while(!test());
    // 三目运算替代if判断生命值
    (life < 0) ? die() : (void)0;
}
  • 所有循环判断、分支选择都通过位运算、三目运算符、查表实现,没有依赖if语句做分支控制
  • 增加了10ms硬件消抖+按键释放等待逻辑,单次按键按下只会触发一次判定,不会连续扣血
  • 去掉了冗余的空语句和不可达代码,两个按键的判定逻辑统一处理,不会出现分支被截断的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 04:18:31