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

Arduino中断异常:方波边沿触发函数未稳定输出串口信息

Troubleshooting Unreliable Interrupt Triggers for Rising/Falling Edges

Hey there! Let's break down why your interrupt setup isn't working as expected and fix it up.

The Core Problem

When you call attachInterrupt() twice on the same pin, the second call completely overwrites the first one. So your initial setup for the rising edge (RISING trigger calling udara()) gets erased when you set the falling edge (FALLING trigger calling blank()). That's why you're seeing inconsistent or missing serial outputs for one of the edges.

The Fix: Use CHANGE Trigger + Level Checking

Instead of trying to bind two separate interrupts to the same pin, use the CHANGE trigger (which fires on both rising and falling edges) and add a quick check inside the interrupt service routine (ISR) to determine which edge just occurred.

Also, a critical rule: never use Serial.print() inside an ISR! Serial communication relies on interrupts, which are disabled during ISR execution—this can cause deadlocks, data loss, or unstable behavior. Instead, use volatile global flags to signal the main loop() to run your functions.

Working Code Example

Here's a revised version of your code that addresses these issues:

const byte interruptPin = 2;
// Volatile flags to signal edge events (prevents compiler optimization bugs)
volatile bool risingEdgeDetected = false;
volatile bool fallingEdgeDetected = false;

void setup() {
  Serial.begin(9600);
  // Set pin mode (use INPUT_PULLUP if your circuit lacks external pull resistors)
  pinMode(interruptPin, INPUT_PULLUP);
  // Attach interrupt for ANY edge change
  attachInterrupt(digitalPinToInterrupt(interruptPin), handleEdgeChange, CHANGE);
}

void loop() {
  // Check flags in main loop and run your custom functions
  if (risingEdgeDetected) {
    udara();
    risingEdgeDetected = false; // Reset flag after handling
  }
  if (fallingEdgeDetected) {
    blank();
    fallingEdgeDetected = false; // Reset flag after handling
  }
}

// Interrupt Service Routine (ISR) - keep this as short as possible!
void handleEdgeChange() {
  if (digitalRead(interruptPin) == HIGH) {
    // This was a rising edge
    risingEdgeDetected = true;
  } else {
    // This was a falling edge
    fallingEdgeDetected = true;
  }
}

// Your custom functions
void udara() {
  Serial.println("Rising edge triggered!");
}

void blank() {
  Serial.println("Falling edge triggered!");
}

Key Notes for Stability

  • Volatile Variables: The flags are marked volatile because they're modified in the ISR and read in the main loop—this tells the compiler not to optimize their values, ensuring consistency between the two contexts.
  • Pin Mode: Use INPUT_PULLUP if your external signal doesn't have built-in pull resistors. This prevents floating pins (which can cause false interrupt triggers). If your signal uses external pull-down resistors, use INPUT instead.
  • Short ISRs: Keep your ISR (handleEdgeChange()) as minimal as possible. Only set flags here—all heavy lifting (like Serial prints or complex logic) should happen in the main loop().

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:02:24