View Categories

Прерывания

При программировании МК доступен один очень мощный инструмент - прерывания (interrupts). Прерывание - это событие, вызываемое периферией МК. Их может быть много разных - например изменение состояния пина, завершение отправки или получение байта данных по интерфейсу связи, срабатывание аппаратного таймера и так далее. Список прерываний и как с ними работать нужно искать в документации на конкретный МК.

Механизм прерываний позволяет "подключить" функцию-обработчик, которая будет вызываться при наступлении соответствующего события. Эта функция вызывается непосредственно в тот момент, когда сработало прерывание - выполнение текущей инструкции прерывается (неважно, что это было - задержка, вычисление выражения...), выполняется функция-обработчик прерывания, затем процессор возвращается к основному коду программы с того места, где прервался.

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

Прерывание в прерывании #

Если внутри обработки функции прерывания сработает другое прерывание - тут могут быть варианты: некоторые процессоры поддерживают вложенные прерывания, некоторые - нет. Во втором случае прерывания встают в очередь согласно приоритету прерываний данного МК и начинают вызываться после обработки функции каждого следующего прерывания. Если вложенные прерывания поддерживаются - может получиться "программа в программе", то есть основная программа будет прерываться на некий код, который тоже может прерываться на другой код.

Код в прерывании #

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

В особо критичных местах в коде программы можно отключать прерывания, чтобы выполнение точно не прерывалось и занимало ожидаемое время - в Arduino есть функции noInterrupts() - запретить прерывания и interrupts() - разрешить их обратно.

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

Прерывания в Arduino #

В Arduino-фреймворке для некоторых плат и МК изначально могут быть настроены и обрабатываться в системных файлах некоторые прерывания.

Например в AVR - по прерываниям аппаратного таймера ведётся счёт времени для функций millis() и micros() - если запретить прерывания - счёт аптайма остановится. В остальное время таймер работает и считает время, пока в программе выполняются вычисления, ожидаются задержки и так далее. Опять же в AVR например нет вложенных прерываний, поэтому внутри обработчика прерывания остальные прерывания запрещаются. Это означает, что если написать свой обработчик прерывания с долгим временем выполнения кода - аптайм может начать отставать от реального времени.

Или например Serial - он имеет буфер для входящих и исходящих данных, поэтому когда мы пишем Serial.print(..) - данные кладутся в буфер, что занимает минимальное время, а отправляются они уже позже - полностью асинхронно в прерываниях. Асинхронно работает и получение данных по UART - по прерыванию они кладутся в буфер приёма, поэтому Serial не пропускает данные даже когда программа ждёт задержку delay или выполняет сложные долгие вычисления.

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Прокрутить вверх