Задержка Arduino внутри прерывания

isr

Использование функции задержки внутри ISR не одобряется при программировании на Arduino. Общий ответ на решение этого желания состоит в том, чтобы спроектировать программу так, чтобы задержка за пределами прерывания была более аккуратной.

Мой вопрос просто в том, почему. Почему размещение задержки() внутри ISR приводит к нестабильному поведению Arduino. Что происходит под капотом?

, 👍2


3 ответа


Лучший ответ:

4

Почему размещение задержки() внутри ISR приводит к нестабильному поведению Arduino? Что происходит под капотом?

Первая проблема заключается в том, что задержка() — это функция мониторинга занятого цикла millis(). Значение, возвращаемое millis(), не изменится внутри ISR, поскольку прерывания внутри ISR отключены; вот почему ISR должны быть как можно более короткими и быстрыми, иначе они будут мешать другим прерываниям

Итак, если вы вызовете метод задержки() внутри ISR, ваш бедный AVR застрянет в тупике! Он ждет чего-то, чего сейчас уже никогда не произойдет.

Вторая проблема заключается в том, что если ваш ISR занимает слишком много времени, вы можете пропустить другие прерывания; millis() и micros() могут пропускать тики и становиться неточными!

,

1

Поскольку задержка внутри прерывания приводит к тому, что это прерывание и другие прерывания (с более низким приоритетом) больше не выполняются, пока задержка не закончится.

Предположим, что в ISR вы обрабатываете входящие байты из UART. Если вы добавите задержку в ISR и буфер UART заполнится, он переполнится, и вы пропустите байты.

,

1

Это дополнение к ответу эзотерика.

В большинстве случаев, когда люди пытаются использовать delay() внутри ISR, это плохой выбор дизайна, даже использовать его в общем виде, что приведет к описанным проблемам (ожидание навсегда или отсутствуют другие прерывания). delay() — простая функция, предназначенная главным образом для новичков, работающих с очень простыми программами. Это простая отправная точка. В большинстве случаев его использование в любой программе не является хорошим выбором, поскольку вы заняты ожиданием и не можете сделать что-то еще (например, ответить на ввод пользователя). Есть более эффективные способы, включающие сам millis(), которые сохраняют расширяемость вашей программы (так что, если вы захотите добавить функциональность, она не будет заблокирована первой частью кода). И когда ваша программа достигает сложности использования собственных ISR, вам следует избегать delay(), если вы действительно не знаете, что делаете.

IMO, на каком-то (довольно раннем) этапе каждый программист Arduino должен научиться использовать millis() для выполнения кода по времени. Вы можете посмотреть пример BlinkWithoutDelay, который поставляется с Arduino IDE.

,