2015-10-27 9 views
3

В следующем коде, почему ISR2 никогда не запускается?Несколько прерываний Arduino на том же выводе

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 края из-за механического отскока. В этом случае я правильно обрабатываю debouncing.

Однако, представьте на некоторое время Концевой выключатель сидел в сцепленном состоянии, а затем я обратный двигатель, вызывающий конечный выключатель для отключения, это будет отправить RISING край с последующим FALLING и RISING краями. Мне нужно игнорировать эти края, потому что ничего не в опасности. Файл ISR2 был записан с целью захвата первого края RISING, когда переключатель Limit отключается, а затем дебютирует его так, что следующие края FALLING игнорируются. Но теперь, когда ISR2 никогда не звонит, как я могу справиться с этой ситуацией?

P.S. Мой микроконтроллер - ATMEGA 2650, это доска Arduino Mega.

+2

Не смотря на техническое описание AVR, я подозреваю, что вы не можете настроить два прерывания на одном и том же выводе.Кажется, он универсален на всех платформах, на которых я работал, и вы получаете один источник прерываний на каждый вывод, и вы можете запускать край, повышение, уровень, падение и т. Д. –

+1

Использование занятого ожидания в ISR является злым! Проверьте исходный код 'delay()' Я уже прокомментировал это по вашему последнему вопросу. Тем не менее, я не знаю, покрывает ли Arduino это в программном обеспечении, но то, что вы делаете, выглядит очень странным и необычным. AVR (как и все другие MCU, которые я знаю) не может использовать два прерывания на одном и том же выводе. Узнайте больше о том, как работают прерывания и аппаратные средства. И как правильно отключить коммутатор. Ваш подход окончательно ошибочен. – Olaf

ответ

7

ISR2 никогда не запускается, потому что для любого источника прерываний может быть только одна процедура обслуживания прерываний, и вы заменили ISR2 на ISR1 как рутину sercice для этого прерывания. Если вы изменили порядок кода и подключили ISR1 до ISR2, вы можете увидеть запуск ISR2, но не ISR1.

Типичный микроконтроллер имеет таблицу векторов прерываний, которая связывает процедуру обслуживания прерываний с каждым источником прерываний. Для каждого источника прерываний может быть только одна сервисная процедура. Если вы назначаете новую сервисную процедуру, вы заменяете старую сервисную процедуру. Для восходящего и спадающего краев нет отдельных сервисных процедур. Восходящий и спадающий фронт - это настройка конфигурации для источника прерывания, чтобы определить, когда это прерывание должно срабатывать. Источник прерывания не может быть настроен для одновременного запуска на обоих краях.

Однако вы можете перенастроить прерывание для другого края после того, как вы получили прерывание для первого края и отменили переход. Таким образом, ваш код будет пинг-понг взад и вперед, настраивая один ISR, а затем другой.

1

Почему вы говорите, что его никогда не называют? Я думаю, что он называется, но вы его не замечаете, потому что светодиод не меняет свое состояние (потому что есть отскоки).

В любом случае, вы НЕ ОТНОСИТСЯ правильно. Давайте сделаем пример: вы нажмете на endstop. ISR1 получает вызов, поэтому flag - это правда. Хорошо, в следующем цикле двигатель будет остановлен. Но ... Теперь переключатель отскакивает. ISR2 вызывается, а функция delay ждет 100 мс перед выходом из ISR. Результат: вы остановили функцию остановки двигателя на 100 мс.

Предлагаю вам прочитать мой ответ here, особенно второй случай. И я предлагаю вам использовать мой код вместо вашего, так как таким образом вы сможете немедленно остановить двигатель, без отскоков или каких-либо других проблем.

Смежные вопросы