多个Arduino中断在同一个引脚上

时间:2015-10-27 23:20:32

标签: arduino embedded debouncing

在以下代码中,为什么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边缘,然后FALLING和{ {1}}边缘。因为没有任何危险,我需要忽略这些边缘。编写RISING的目的是在限位开关脱离时捕获第一个ISR2边,然后对其进行去抖动,以便忽略以下RISING边。但是现在FALLING永远不会被调用,我怎么能处理这种情况呢?

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

2 个答案:

答案 0 :(得分:8)

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

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

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

答案 1 :(得分:1)

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

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

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