同一引脚上的多个 Arduino 中断

Multiple Arduino Interrupts on same pin

在下面的代码中,为什么 ISR2 永远不会 运行?

const int in = 19;
const int LED = 9;
int flag;
void setup() {
    pinMode(in, INPUT_PULLUP);
    pinMode(LED, OUTPUT);
    attachInterrupt(digitalPinToInterrupt(in), ISR2, RISING);
    attachInterrupt(digitalPinToInterrupt(in), ISR1, FALLING);

}
void  loop() {
    if (flag) {delay (100); flag = false;}// debounce
}
void ISR1(){
    digitalWrite(LED, LOW);
    // Turn Off the motor, since, Limit Switch was engaged
    flag = true;
}
void ISR2(){ // Limit Switch was disengaged. 
    digitalWrite(LED, HIGH);
    delay(100); // Debounce, so I do not receive spurious FALLING edges from this.
}

Arduino 是否不允许您在同一个引脚上附加两个中断,即使中断是为不同的事件编程的?

在我的设置中,引脚 19 从运动控制设置中使用的限位开关获取信号。当限位开关接合时,in 引脚获得 LOW 信号。因此,由于机械反弹,我首先看到 FALLING 边缘,然后是 RISING 边缘和 FALLING 边缘。在这种情况下,我正确处理了去抖动。

但是,假设限位开关处于接合状态一段时间,然后我反转电机导致限位开关脱离,这将发送一个 RISING 边沿,然后是 FALLINGRISING 边。我需要忽略这些边缘,因为没有任何危险。 ISR2 的目的是在限位开关断开时捕获第一个 RISING 边缘,然后对其进行去抖动,以便忽略以下 FALLING 边缘。但是现在 ISR2 永远不会被调用,我该如何处理这种情况?

P.S。我的微控制器是 ATMEGA 2650,它是一块 Arduino Mega 开发板。

你为什么说它永远不会被调用?我认为它被调用了,但你没有注意到它,因为 led 不会改变它的状态(因为有反弹)。

无论如何,你没有正确地去抖动。让我们举个例子:你到达终点。 ISR1 被调用,所以 flag 为真。好的,在下一个循环中电机将停止。但是......现在开关弹跳了。 ISR2 被调用,其中的 delay 函数在退出 ISR 之前等待 100ms。结果:您将电机停止功能延迟了 100 毫秒。

我建议你阅读我的回答,尤其是第二种情况。我建议您使用我的代码而不是您的代码,因为这样您就可以立即停止电机,而不会出现反弹或任何其他类型的问题。

ISR2 永远不会 运行s 因为任何中断源只能有一个中断服务例程,并且您已将 ISR2 替换为 ISR1 作为此中断的服务例程。如果您重新排序代码并在 ISR2 之前附加 ISR1,那么您可能会看到 ISR2 运行 而不是 ISR1.

典型的微控制器有一个中断向量 table,它将中断服务例程与每个中断源相关联。每个中断源只能有一个服务程序。如果您分配了一个新的服务例程,那么您将替换旧的服务例程。上升沿和下降沿没有单独的服务例程。上升沿与下降沿是中断源的配置设置,用于确定何时触发中断。中断源不能配置为同时触发两个边沿。

但是,在收到第一个边沿的中断并对转换进行去抖动后,您可以重新配置另一个边沿的中断。通过这种方式,您的代码将为一个 ISR 和另一个 ISR 来回配置。