如何使用串口作为其他功能的中断

How to use Serial as an interrupt for other functions

我正在制作一个 LED 控制程序(当然使用 FastLED)并使用串行(带有串行监视器)来控制它。只需通过 USB 连接,大部分情况下工作正常。然而,我注意到长而闪烁的例程我无法阻止它们并让 LED 做其他事情。我代码中的flash例程很简单:

void flash(CRGB color, int count, int del){
  for(int i = 0; i < count; i++){
    if(pause){
      break;
    }
    fillLeds(color.r, color.g, color.b);
    milliDelay(del);
    fillLeds(0,0,0);
    milliDelay(del);
  }
}

fillLeds(r,g,b) 是一个 for 循环,遍历并将所有 LED 设置为特定颜色,而 milliDelay 只是 delay() 使用 millis 而不是 delay() 函数。我需要的是不仅可以暂停这个,还可以暂停其他功能(可能使用 break;),然后执行其他代码。看起来很容易吧?好吧,我注意到当我通过串行发送一个字节时,如果你愿意的话,它会进入这个 "queue,",然后被顺序读取。我不能让这种事发生。我需要的是进入 Serial 的下一个字节来激活某种暂停其他 flash() 函数 运行 的事件,然后被使用。我实现这个的方式是这样的:

void loop()
{
    if (Serial.available() > 0) {
      int x = Serial.read();
      Serial.print(x);
      handleRequest(x);
    }

    FastLED.show();
    FastLED.delay(1000 / UPDATES_PER_SECOND);
}

其中 handleRequest(x); 只是一个很长的 switch 语句,调用了 flash 方法,使用了不同的颜色等。

如何让 Arduino 在收到新字节时暂停其他循环,而不是将其添加到此 "queue" 以供稍后执行?如果这是不可能的,感谢您阅读。我试过使用 serialEvent(),但似乎不起作用。

据我了解,您希望在新字节到达时具有类似中断的功能吗?

不幸的是,serialEvent并且不是真正的中断。如果有可用的串行数据,它仅在 loop 结束时运行。

但是,serialEvent 只是一个函数,您没有理由不能在代码中随心所欲地调用它。这实际上是尽可能频繁地轮询新的串行数据。因此,虽然您的循环是 运行,但在您的延迟期间调用 serialEvent 并在那里处理串行数据。

您可能需要重构代码以避免递归。如果 flash 调用 serialEvent,后者调用 flash,后者调用 serialEvent 等等...那么您最终可能会溢出堆栈。

我认为你需要 2 个循环。你有一个,这是你的主循环,你可以用 TimerOne 库添加另一个(比如多线程)。像这样:

Timer1.initialize(your desired delay in this loop);
Timer1.attachInterrupt( your desired function in this loop);

因此,您可以在第二个循环中添加带有 var 的 if 语句,以阻止某些功能并在第一个循环中更新 var 或类似的东西。