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

如何通过物理按键终止Arduino程序中正在执行的if条件分支

物理按键终止运行中逻辑的实现方案

完全可以实现,你现有代码无法响应终止按键的核心原因是delay()为阻塞函数,执行delay时MCU会停在当前位置等待计时结束,不会执行按键读取、状态判断等其他代码,因此按下按键不会被识别。
下面提供3种不同改造成本的实现方案:

方案1:拆分阻塞delay(改动最小,适合新手)

如果对计时精度要求不高,只需要把长delay拆分为多次短delay,每次短delay后都检测一次终止按键状态即可,单份delay的拆分粒度越小,按键响应速度越快:

void loop() {
  val = digitalRead(pushbutton);
  zhar = digitalRead(pushbutton1);
  bool abortFlag = false;

  if (val == LOW) {
    digitalWrite(fan, HIGH);
    // 拆分15分钟delay为100ms一次的循环,每次检测按键
    for(int i=0; i<9000; i++) {
      delay(100);
      if(digitalRead(pushbutton1) == LOW) {
        abortFlag = true;
        break;
      }
    }
    if(abortFlag) {
      digitalWrite(fan, LOW);
      return;
    }

    for (int x = 0; x < 20; x++) {
      digitalWrite(fan, LOW);
      delay(400);
      if(digitalRead(pushbutton1) == LOW) {
        abortFlag = true;
        break;
      }

      digitalWrite(fan, HIGH);
      // 拆分15s delay
      for(int i=0; i<150; i++) {
        delay(100);
        if(digitalRead(pushbutton1) == LOW) {
          abortFlag = true;
          break;
        }
      }
      if(abortFlag) break;

      digitalWrite(fan, LOW);
      delay(2000);
      if(digitalRead(pushbutton1) == LOW) {
        abortFlag = true;
        break;
      }
    }
    if(abortFlag) {
      digitalWrite(fan, LOW);
    }
  } else {
    digitalWrite(fan, LOW);
  }
}

方案2:非阻塞计时(推荐,无硬件改动)

使用Arduino内置的millis()函数做计时,完全替换掉阻塞的delay(),程序全程不会被卡住,随时可以响应按键操作,计时精度更高:
首先定义全局变量:

unsigned long previousMillis = 0;
bool taskRunning = false;
int taskStep = 0;
int loopCount = 0;
int loopStep = 0;
bool abortTask = false;
const long interval_15min = 900000;
const long interval_400ms = 400;
const long interval_15s = 15000;
const long interval_2s = 2000;

主逻辑代码:

void loop() {
  val = digitalRead(pushbutton);
  zhar = digitalRead(pushbutton1);
  // 检测终止按键
  if (zhar == LOW) {
    abortTask = true;
    taskRunning = false;
    digitalWrite(fan, LOW);
    taskStep = 0;
    loopCount = 0;
    loopStep = 0;
  }

  // 启动风扇任务
  if (val == LOW && !taskRunning && !abortTask) {
    taskRunning = true;
    taskStep = 1;
    previousMillis = millis();
    digitalWrite(fan, HIGH);
  }

  // 非阻塞执行任务
  if (taskRunning && !abortTask) {
    unsigned long currentMillis = millis();
    switch(taskStep) {
      case 1: // 执行15分钟高电平
        if (currentMillis - previousMillis >= interval_15min) {
          previousMillis = currentMillis;
          taskStep = 2;
          loopCount = 0;
          digitalWrite(fan, LOW);
        }
        break;
      case 2: // 执行20次循环
        if (loopCount < 20) {
          switch(loopStep) {
            case 0: // 低电平400ms
              if (currentMillis - previousMillis >= interval_400ms) {
                previousMillis = currentMillis;
                digitalWrite(fan, HIGH);
                loopStep = 1;
              }
              break;
            case 1: // 高电平15s
              if (currentMillis - previousMillis >= interval_15s) {
                previousMillis = currentMillis;
                digitalWrite(fan, LOW);
                loopStep = 2;
              }
              break;
            case 2: // 低电平2s
              if (currentMillis - previousMillis >= interval_2s) {
                previousMillis = currentMillis;
                loopCount++;
                loopStep = 0;
              }
              break;
          }
        } else {
          // 任务执行完成重置状态
          taskRunning = false;
          taskStep = 0;
          loopCount = 0;
          loopStep = 0;
        }
        break;
    }
  } else {
    digitalWrite(fan, LOW);
    // 松开终止按键后重置标记
    if (zhar == HIGH) {
      abortTask = false;
    }
  }
}

方案3:外部中断(响应速度最快)

如果对终止按键的响应速度要求极高,可以把终止按键接到MCU的外部中断专用引脚(比如Arduino UNO的D2、D3引脚),触发中断时直接修改终止标记位,就算主逻辑有短暂阻塞也能正常响应终止操作。

注意事项

  • 机械按键存在物理抖动,建议添加10~20ms的消抖逻辑,避免误触发,可以在第一次检测到按键按下后延时10ms再读一次状态,确认按下再触发终止操作
  • 所有方案中终止按键的触发逻辑可以根据你的实际接线调整,默认假设按下为低电平

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 10:12:00