同一引脚上的多个 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
边沿,然后是 FALLING
和 RISING
边。我需要忽略这些边缘,因为没有任何危险。 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 来回配置。
在下面的代码中,为什么 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
和 RISING
边。我需要忽略这些边缘,因为没有任何危险。 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 来回配置。