Главная chevron_right Функции chevron_right Прерывания chevron_right noInterrupts()

noInterrupts()

noInterrupts() отключает все аппаратные прерывания — удобно для защиты критичных участков кода, работающих с long, float или точными таймингами.

Полная статья

Описание

Функция noInterrupts() запрещает обработку аппаратных прерываний. По умолчанию прерывания в Arduino включены: они позволяют микроконтроллеру реагировать на внешние события и выполнять фоновые задачи — например, получать данные по Serial или отсчитывать время с помощью millis(). Иногда, однако, прерывание в самый неподходящий момент может нарушить тайминг критичного участка кода. Именно для таких случаев и нужна noInterrupts().

После того как вы защитили нужный участок, обязательно снова включите прерывания с помощью interrupts() — иначе часть функций Arduino перестанет работать корректно.

Синтаксис

noInterrupts()

Параметры

Функция не принимает параметров.

Возвращает

Ничего не возвращает.

Пример кода

void setup() {}

void loop() {
  noInterrupts();
  // критический, чувствительный ко времени код
  interrupts();
  // остальной код
}

Где применяется

  • Работа с многобайтовыми переменными. Если прерывание может изменить переменную в середине её чтения или записи (например, long или float), данные окажутся повреждены. noInterrupts() защищает такие операции.
  • Точное управление временем. При генерации импульсов с жёсткими требованиями к длительности прерывания могут сдвинуть момент смены состояния вывода.
  • Работа с аппаратными протоколами без аппаратной поддержки. Программная реализация протоколов, чувствительных к задержкам, требует гарантированного выполнения без пауз.
  • Атомарное чтение данных от ISR. Если обработчик прерывания обновляет переменную, которую читает основной цикл, нужно на момент чтения заблокировать прерывания, чтобы получить согласованное значение.

Практические замечания

  • Всегда включайте прерывания обратно. Вызов noInterrupts() без последующего interrupts() — распространённая ошибка. millis() и delay() перестанут работать правильно, Serial перестанет принимать данные.
  • Держите защищённый участок как можно короче. Чем дольше прерывания отключены, тем больше событий будет пропущено: входящие байты Serial, импульсы энкодера, тики таймера.
  • Вложенные вызовы не поддерживаются. Если вы вызовете noInterrupts() дважды подряд, один вызов interrupts() всё равно включит прерывания — счётчика вложенности нет.
  • Прерывания не буферизуются. Событие, которое произошло во время блокировки, будет потеряно — за исключением случаев, когда аппаратный буфер (например, UART FIFO) успел его сохранить.
  • Осторожно на платах с нативным USB. На платах вроде Arduino Leonardo длительное отключение прерываний может нарушить USB-обмен с компьютером. В результате плата может временно перестать отвечать как последовательный порт, пока прерывания не будут снова включены.

Примечания и предупреждения

На платах с нативным USB не держите прерывания отключёнными дольше необходимого: это может нарушить работу USB Serial и сделать отладку через Serial Monitor нестабильной.

Полезные материалы