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 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОК