Прерывание (interrupt) - это сигнал, сообщающий процессору о наступлении некоторого события, требующего немедленной обработки. Процессор приостанавливает текущую активность, сохраняя свое состояние, передает управление обработчику прерывания, после чего возвращает управление в прерванный код.
Для работы с прерываниями в Arduino есть 2 функции:
- attachInterrupt()
- detachInterrupt()
Функция attachInterrupt()
Описание
Задает функцию, которая будет вызвана по внешнему прерыванию. Если функция уже была задана, то она будет заменена на новую. Рекомендуется использовать функцию digitalPinToInterrupt(pin) для перевода номера пина в номер прерывания. Например, если вы подключены к пину 3, используйте digitalPinToInterrupt(3) в качестве первого параметра attachInterrupt().
Плата Arduino | Пины, используемые для прерываний |
---|---|
Arduino Uno, Arduino Nano, Arduino Mini и остальные на ATmega328 | 2, 3 |
Arduino Mega, Arduino Mega2560 | 2, 3, 18, 19, 20, 21 |
Arduino Micro, Arduino Leonardo и остальные на ATmega32U4 | 0, 1, 2, 3, 7 |
Arduino Zero | все цифровые пины кроме 4 |
Arduino Due | все цифровые пины |
Прерывания полезны, когда нужно читать значения с некоторых датчиков или обслуживать ввода пользователя.
ISR (Interrupt Service Routine) - это особые функции, которые имеют некоторые уникальные ограничения, которых нет у большинства других функций. ISR не может иметь никаких параметров, и они не должны ничего возвращать.
Как правило, функция ISR должна быть максимально короткой и быстрой. Если в одной программе задано несколько ISR-функций, то одновременно выполняться может только одна, остальные будут выполняться после завершения текущей в порядке, заданным приоритетом. Функция millis() использует прерывания для подсчета, поэтому возвращаемое ей значение не будет увеличиваться внутри ISR. Поскольку функции delay() для работы требуются прерывания, он тоже не будет работать. micros() сначала будет работает, но через 1-2 мс начнет возвращать неверный беспорядочный результат. delayMicroseconds() не использует счетчик, поэтому она будет работать как обычно.
Обычно для передачи данных между функциями ISR и основной программой используются глобальные переменные. Чтобы быть уверенными, что переменные, общие для ISR и основной программы, будут работать правильно, следует объявить их как volatile.
Синтаксис
attachInterrupt(digitalPinToInterrupt(pin), ISR, mode) - правильное использование
attachInterrupt(interrupt, ISR, mode) - так использовать не рекомендуется
attachInterrupt(pin, ISR, mode) - так использовать не рекомендуется (только для плат Arduino SAMD, Arduino Uno WiFi Rev2, Arduino Due, Arduino 101)
Параметры
interrupt - номер прерывания
pin - номер пина
ISR - функция для вызова при возникновении прерывания; эта функция не должна принимать никаких параметров и ничего не должна возвращать; эту функцию иногда называют процедурой обработки прерываний
mode - определяет, когда прерывание должно быть запущено
Допустимые значения параметра mode:
- LOW - вызов прерывания когда на пине значение LOW
- CHANGE - вызов прерывания когда на пине меняется значение
- RISING - вызов когда значение переходит от LOW к HIGH
- FALLING - вызов когда значение переходит от HIGH к LOW
- HIGH (доступно только для Arduino Due, Arduino Zero) - вызов прерывания когда на пине значение HIGH
Возвращаемое значение
нет
Пример
Зажигаем и гасим встроенный светодиод при изменении сигнала на 2 пине:
const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;
void setup()
{
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
}
void loop()
{
digitalWrite(ledPin, state);
}
void blink()
{
state = !state;
}
Примечания
Внутри функции, вызываемой по прерыванию, функции delay() работать не будет, а возвращаемое функцией millis() значение не будет увеличиваться. Последовательные данные, полученные во время использования функции, могут быть потеряны. Вы должны объявить как volatile любые переменные, которые вы изменяете в функции.
Функция detachInterrupt()
Описание
Отключает прерывание.
Синтаксис
detachInterrupt(digitalPinToInterrupt(pin)) - правильное использование
detachInterrupt(interrupt) - так использовать не рекомендуется
detachInterrupt(pin) - так использовать не рекомендуется (только для плат Arduino SAMD, Arduino Uno WiFi Rev2, Arduino Due, Arduino 101)
Параметры
interrupt - номер прерывания, которое нужно отключить
pin - номер пина прерывания для отключения
Возвращаемое значение
нет