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

嵌入式C编程:IF语句功能异常问题排查

Arduino Mega按键控制LED功能修复

问题说明

需求如下:

  • 按住PORTK PK1(Switch1)后,每按一次PORTK PK0(Switch2),Port F的0-3号LED依次点亮
  • 先按两次Switch2,再按住Switch1时,每按一次Switch2,Port F的4-7号LED依次点亮
    当前仅第一种功能正常,第二种逻辑完全无法触发。

原代码问题分析

  1. 状态记录缺失:代码完全没有记录“先按两次Switch2”这个前置操作的状态,根本无法触发第二种逻辑
  2. 无效判断逻辑:j变量仅在按住Switch1时被设为1,j/2结果为0(整数除法),导致第一个if块永远不会执行;j%2结果为1,重复处理第一种情况,完全没涉及第二种功能
  3. 阻塞式消抖:用for循环延时做消抖,会阻塞程序运行,导致按键状态检测不及时,甚至错过按键事件
  4. 逻辑结构混乱:重复的LED控制代码,没有区分不同触发条件的分支

修正后的代码

void setup() {
  DDRF = 0xFF;  // Port F设为输出(控制LED)
  DDRK = 0x00;  // Port K设为输入(读取按键)
  PORTK = 0x03; // 给PK0、PK1引脚配置内部上拉电阻,按键接地时触发

  // 状态变量定义
  static uint8_t switch2_count = 0;      // 记录Switch2的独立按下次数
  static uint8_t led_state_low = 0;      // F0-F3的LED循环状态
  static uint8_t led_state_high = 0;     // F4-F7的LED循环状态
  static bool switch1_prev = HIGH;       // Switch1上一次状态
  static bool switch2_prev = HIGH;       // Switch2上一次状态
  const unsigned long debounce_time = 50;// 消抖延时50ms
  unsigned long last_switch1_time = 0;   // Switch1最后触发时间
  unsigned long last_switch2_time = 0;   // Switch2最后触发时间

  while (1) {
    unsigned long current_time = millis();
    // 读取当前按键状态(低电平表示按下)
    bool switch1_curr = (PINK & 0x02) == 0x00;
    bool switch2_curr = (PINK & 0x01) == 0x00;

    // 处理Switch1未按住时的Switch2计数
    if (!switch1_curr) {
      if (switch2_curr != switch2_prev && current_time - last_switch2_time > debounce_time) {
        last_switch2_time = current_time;
        switch2_prev = switch2_curr;
        if (switch2_curr) { // 按键按下时计数,超过2次重置
          switch2_count++;
          switch2_count = switch2_count > 2 ? 0 : switch2_count;
        }
      }
    }

    // 处理Switch1的消抖
    if (switch1_curr != switch1_prev && current_time - last_switch1_time > debounce_time) {
      last_switch1_time = current_time;
      switch1_prev = switch1_curr;
    }

    // 处理按住Switch1时的LED控制
    if (switch1_curr) {
      if (switch2_curr != switch2_prev && current_time - last_switch2_time > debounce_time) {
        last_switch2_time = current_time;
        switch2_prev = switch2_curr;
        if (switch2_curr) {
          if (switch2_count == 2) { // 前置按过两次Switch2,控制F4-F7
            led_state_high++;
            led_state_high = led_state_high > 4 ? 1 : led_state_high;
            PORTF = (1 << (led_state_high + 3)); // 映射到F4-F7引脚
          } else { // 控制F0-F3
            led_state_low++;
            led_state_low = led_state_low > 4 ? 1 : led_state_low;
            PORTF = (1 << (led_state_low - 1)); // 映射到F0-F3引脚
          }
        }
      }
    }
  }
}

void loop() {
  // 空loop,逻辑已在setup的while循环中实现
}

修正要点

  • 增加状态记录:用switch2_count记录Switch2的独立按下次数,作为第二种LED逻辑的触发条件
  • 非阻塞消抖:用millis()实现消抖,避免阻塞程序,保证按键检测的灵敏性
  • 清晰分支逻辑:拆分“Switch1未按住时的计数”和“Switch1按住时的LED控制”两个独立逻辑分支
  • 硬件适配:配置引脚内部上拉电阻,简化按键接线(按键一端接引脚,另一端接地)
  • 状态循环重置:LED状态计数超过上限时自动重置,保证LED循环点亮

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 09:01:21