12.2. Что выбрать: опрос состояния в цикле или прерывания?

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

12.2.1. Программная реализация

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

12.2.2. Аппаратная реализация

С точки зрения аппаратной реализации между опросом контакта в цикле и прерыванием нет разницы, т. к. в обоих случаях считывается состояние входа. Тем не менее, при наличии дребезга ( см. главу 2) возникает серьезная проблема: процедура обработки прерывания может быть вызвана несколько раз. Самое неприятное, что в процедуре обработки прерывания нельзя задействовать функцию программного устранения дребезга, потому что невозможен вызов функции ctelay(). Поэтому, если вы хотите использовать прерывание для входа с дребезгом, необходимо устранить дребезг аппаратно.

12.2.3. Многозадачность

Одна из причин использования прерываний - предоставление псевдомногозадачности. С помощью Arduino никогда нельзя обеспечить реальную многозадачность, т. к. на плате только один микроконтроллер, который за один такт может выполнить только одну команду. Однако, поскольку микроконтроллер выполняет команды очень быстро, можно прибегнугь к прерываниям, чтобы выполнять разные задачи почти одновременно. Например, с помощью прерывания можно в про-

- 256 -

цессе уменьшения яркости светодиодов реагировать на нажатие кнопки, которая регулирует скорость или цвет. В то время как при опросе контакта в цикле можно прочитать значение входа кнопки командой dig i talRead() только один раз и имеющиеся в цикле loop() "медленные" операции снижают эффективность контроля входа кнопки.

12.2.4. Точность сбора данных

Для некоторых задач, где требуется быстрый сбор данных, прерывания являются необходимостью. Один из примеров - энкодер, смонтированный на двигателе постоянного тока, отправляющий в микроконтроллер импульс при определенном числе оборотов вала. Так осуществляется следящая обратная связь за скоростью вращения двигателя постоянного тока. Это позволяет динамически регулировать скорость в зависимости от нагрузки или отслеживать поворот вала двигателя. Но в такой системе исключительно важно быть уверенным, что плата Arduino получает каждый импульс. Поскольку импульсы очень короткие (намного короче импульса при нажатии кнопки), то при опросе в цикле loop() их можно пропустить. Если энкодер посылает импульс два раза за оборот вала двигателя, то из-за пропуска одного импульса измеренная частота вращения окажется вдвое меньше истинной. Поэтому в данном случае без аппаратного прерывания не обойтись.

12.2.5. Реализация аппаратного прерывания в Arduino

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

Таблица 12.1. Аппаратные прерывания на различных платах Arduino

Плата

INTO

INT1

INT2

INT3

INT4

INT5

UNO,

Ethernet

Pin2

Pin3

-

-

-

-

Mega2560

Pin2

Pin3

Pin21

Pin20

Pin19

Pin18

Leonardo

Pin3

Pin2

Pin0

Pin1

-

-

Для вызова прерывания существует встроенная функция attachInterrupt(). Ее первый аргумент - это идентификатор прерывания (для плат из табл. 12.1) или номер контакта Arduino (для платы Due). Если на плате Arduino Uno вы хотите назначить прерывание физическому контакту 2, то первый аргумент функции attachInterrupt() будет 0. Arduino Uno (и другие платы на базе ATmega328) поддерживает всего два внешних прерывания, платы Mega и Leonardo больше (см. табл. 12.1).

- 257 -

Аппаратные прерывания осуществляют переход к выполненшо определенных функций. Второй аргумент функции attach_interrupt() - имя выполняемой функции. Если вы хотите переключать состояние логической переменной при каждом прерывании, то функция обработки прерывания будет выглядеть так:

void toggleLed()

{

var = !var;

}

При вызове этой функции переменная var переключается в состояние, противоположное предыдущему, и происходит возврат в основную программу. Последний аргумент функции attachInterrupt() - режим запуска прерывания. Существуют режимы LOW, CHANGE, RISING и FALLING (для платы Due также есть режим HIGH).

Режимы CHANGE, RISING и FALLING наиболее популярны, потому что прерывание выполняется только один раз при изменении состояния входа. Режимы HIGH и LOW встречаются реже, потому что будут вызывать процедуру обработки прерывания непрерывно, блокируя остальную часть программы.

Более 800 000 книг и аудиокниг! 📚

Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением

ПОЛУЧИТЬ ПОДАРОК