Что такое аппаратные прерывания в Arduino. Как работает функция attachInterrupt(). Какие платы Arduino поддерживают прерывания. Как правильно настроить и использовать прерывания в своих проектах.
Что такое аппаратные прерывания в Arduino и зачем они нужны
Аппаратные прерывания — это мощный инструмент в Arduino, позволяющий мгновенно реагировать на внешние события. Они позволяют прервать выполнение основной программы и немедленно запустить специальную функцию-обработчик при наступлении определенного условия.
Основные преимущества использования прерываний:
- Мгновенная реакция на события без постоянного опроса
- Экономия ресурсов микроконтроллера
- Возможность обработки критически важных событий в реальном времени
- Упрощение кода за счет выделения обработки событий в отдельные функции
Функция attachInterrupt(): синтаксис и параметры
Для работы с прерываниями в Arduino используется функция attachInterrupt(). Ее синтаксис выглядит следующим образом:
attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);
Параметры функции:
- pin — номер пина Arduino, к которому подключен источник прерывания
- ISR — имя функции-обработчика прерывания
- mode — режим срабатывания прерывания (LOW, CHANGE, RISING, FALLING)
Функция digitalPinToInterrupt() используется для преобразования номера пина в номер прерывания, что обеспечивает совместимость кода между разными платами Arduino.
Поддержка прерываний на различных платах Arduino
Не все пины на платах Arduino поддерживают функцию прерываний. Рассмотрим, какие пины можно использовать на популярных моделях:
- Arduino Uno, Nano, Mini: пины 2 и 3
- Arduino Mega, Mega2560: пины 2, 3, 18, 19, 20, 21
- Arduino Leonardo: пины 0, 1, 2, 3, 7
- Arduino Due: все цифровые пины
- Arduino MKR Family: пины 0, 1, 4, 5, 6, 7, 8, 9, A1, A2
При разработке проектов важно учитывать ограничения конкретной платы по количеству доступных прерываний.
Режимы срабатывания прерываний в Arduino
Arduino поддерживает 4 режима срабатывания прерываний:
- LOW — прерывание срабатывает, когда на пине низкий уровень сигнала
- CHANGE — срабатывание при любом изменении состояния пина
- RISING — срабатывание при переходе сигнала из низкого уровня в высокий
- FALLING — срабатывание при переходе из высокого уровня в низкий
Выбор режима зависит от конкретной задачи и типа подключенного устройства. Например, для кнопки обычно используют FALLING или RISING, а для энкодера — CHANGE.
Особенности написания функций-обработчиков прерываний (ISR)
При создании функций-обработчиков прерываний (Interrupt Service Routine, ISR) необходимо учитывать ряд важных особенностей:
- Функция не должна иметь параметров и возвращаемого значения
- Внутри функции нельзя использовать delay() и millis()
- Функция должна быть максимально короткой и быстрой
- Следует избегать сложных вычислений и длительных операций
- Для передачи данных между ISR и основной программой используются volatile-переменные
Пример правильно оформленной функции-обработчика:
volatile int counter = 0;
void buttonISR() {
counter++;
}
Практические примеры использования attachInterrupt() в проектах
Рассмотрим несколько практических примеров использования прерываний в проектах Arduino:
1. Счетчик нажатий кнопки
const int buttonPin = 2;
volatile int buttonPresses = 0;
void setup() {
Serial.begin(9600);
pinMode(buttonPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(buttonPin), buttonISR, FALLING);
}
void loop() {
Serial.println(buttonPresses);
delay(1000);
}
void buttonISR() {
buttonPresses++;
}
2. Измерение частоты импульсов
const int inputPin = 2;
volatile unsigned long pulseCount = 0;
unsigned long lastTime = 0;
void setup() {
Serial.begin(9600);
pinMode(inputPin, INPUT);
attachInterrupt(digitalPinToInterrupt(inputPin), pulseISR, RISING);
}
void loop() {
if (millis() - lastTime >= 1000) {
noInterrupts();
unsigned long frequency = pulseCount;
pulseCount = 0;
interrupts();
Serial.print("Frequency: ");
Serial.print(frequency);
Serial.println(" Hz");
lastTime = millis();
}
}
void pulseISR() {
pulseCount++;
}
Типичные ошибки при работе с прерываниями и как их избежать
При использовании прерываний в Arduino проектах часто встречаются следующие ошибки:
- Длительные операции в ISR: Выполнение долгих операций в обработчике прерывания может привести к пропуску других прерываний и нестабильной работе программы.
- Использование delay() в ISR: Функция delay() не работает в обработчиках прерываний, так как сама основана на прерываниях.
- Отсутствие защиты общих данных: При обмене данными между ISR и основной программой необходимо использовать volatile-переменные и атомарные операции.
- Игнорирование дребезга контактов: При работе с механическими кнопками необходимо реализовать программную защиту от дребезга.
- Превышение количества доступных прерываний: Важно учитывать ограничения конкретной платы Arduino по количеству поддерживаемых прерываний.
Чтобы избежать этих ошибок, соблюдайте следующие рекомендации:
- Делайте ISR максимально короткими, выполняя основную логику в loop()
- Используйте флаги для передачи информации о событиях из ISR в основную программу
- Применяйте volatile-переменные и атомарные операции для защиты общих данных
- Реализуйте программную защиту от дребезга контактов
- Внимательно изучайте документацию к вашей плате Arduino
Альтернативы attachInterrupt(): другие способы обработки событий в Arduino
Хотя attachInterrupt() является мощным инструментом, в некоторых случаях могут быть более подходящие альтернативы:
1. Регулярный опрос (polling)
Для несложных проектов с некритичным временем реакции можно использовать простой опрос состояния пинов в функции loop():
void loop() {
if (digitalRead(buttonPin) == LOW) {
// Обработка нажатия кнопки
}
}
2. Библиотека TimerOne
Эта библиотека позволяет настроить прерывания по таймеру, что удобно для выполнения регулярных задач:
#include <TimerOne.h> void setup() { Timer1.initialize(1000000); // 1 секунда Timer1.attachInterrupt(timerISR); } void timerISR() { // Код, выполняемый каждую секунду }
3. Порты ввода-вывода
Для более продвинутых пользователей возможна прямая работа с портами ввода-вывода, что обеспечивает максимальную скорость:
DDRD &= ~(1 << DDD2); // Настройка пина 2 на вход
PORTD |= (1 << PORTD2); // Включение подтягивающего резистора
if (!(PIND & (1 << PIND2))) {
// Обработка нажатия кнопки
}
Выбор метода обработки событий зависит от конкретной задачи, требований к скорости реакции и сложности проекта. В большинстве случаев attachInterrupt() предоставляет оптимальный баланс между простотой использования и эффективностью.
SAMD_TimerInterrupt — библиотеки Arduino
Эта библиотека позволяет использовать прерывания от аппаратных таймеров на платах на основе SAMD, таких как SAMD21 Nano-33-IoT, Adafruit SAMD51 Itsy-Bitsy M4, SeeedStudio XIAO, Sparkfun SAMD51_MICROMOD и т. д.
- Автор
- Кхой Хоанг
- Веб-сайт
- https://github.com/khoih-prog/SAMD_TimerInterrupt
- Категория
- Управление устройствами
- Лицензия
- Массачусетский технологический институт
- Тип библиотеки
- Добавлено
- Архитектуры
- Самд
Эти аппаратные таймеры SAMD, использующие прерывание, продолжают работать, даже если другие функции блокируются. Более того, они намного более точны (конечно, в зависимости от точности тактовой частоты), чем другие программные таймеры, использующие millis() или micros(). Это обязательно, если вам нужно измерить некоторые данные, требующие большей точности. Теперь он поддерживает 16 таймеров на основе ISR, потребляя при этом только 1 аппаратный таймер. Интервал таймера очень длинный (ulong миллисекунды). Наиболее важной особенностью является то, что они основаны на таймерах ISR. Следовательно, их выполнение не блокируется функциями или задачами с плохим поведением. Эта важная функция абсолютно необходима для критически важных задач. SAMD21 теперь может использовать 6 таймеров
Имя файла | Дата выпуска | Размер файла |
---|---|---|
SAMD_TimerInterrupt-1.10.1.zip | 2022-09-29 | 495,12 КиБ |
SAMD_TimerInterrupt-1.10.0.zip | 2022-09-29 | 494,93 КиБ |
SAMD_TimerInterrupt-1.9.0.zip | 2022-05-08 | 469,13 КиБ |
SAMD_TimerInterrupt-1.8.0.zip | 2022-05-07 | 464,90 КиБ |
SAMD_TimerInterrupt-1. 7.0.zip | 2022-04-25 | 465,18 КиБ |
SAMD_TimerInterrupt-1.6.0.zip | 2022-01-21 | 416,85 КиБ |
SAMD_TimerInterrupt-1.5.0.zip | 2021-10-08 | 417,98 КиБ |
SAMD_TimerInterrupt-1.4.0.zip | 2021-06-02 | 301,00 КиБ |
SAMD_TimerInterrupt-1.3.1.zip | 2021-05-09 | 278,18 КиБ |
SAMD_TimerInterrupt-1.3.0.zip | 2021-04-03 | 274,09 КиБ |
SAMD_TimerInterrupt-1.2.0.zip | 2021-01-10 | 252,40 КиБ |
SAMD_TimerInterrupt-1.1.1.zip | 2020-12-07 | 234,32 КиБ |
SAMD_TimerInterrupt-1. | 2020-11-07 | 218,56 КиБ |
SAMD_TimerInterrupt-1.0.0.zip | 2020-11-04 | 212,13 КиБ |
Прерывание подключения Arduino | КодигоЭлектроника
- Описание
- Сосны наперстянки с перерывами
- Acerca de las rutinas de servicio de interrupción
- Номер прерывания
- Синтаксис
- Параметры
- Деволюция
- Ссылки
Описание
Las Interrupciones Son útiles para hacer que las acciones o eventos sucedan automáticamente en los programas de microcontrolador y pueden ayudar a resolver Problemas de tiempo y ejecucion de los mismos. Las buenas tareas para usar una interrupción pueden incluir leer un interruptor o pulsador, hasta codificador rotatorio o monitorear la entrada del usuario.[1]
Сосны наперстянки с перерывами
Начальный параметр для attachInterrupt()
— номер прерывания. Normalmente debe usar digitalPinToInterrupt(pin)
для преобразования цифрового реального PIN-кода в специальный номер прерывания. Например, подключите его к контакту 3, используя digitalPinToInterrupt(3)
, как основной параметр для attachInterrupt()
.
La siguiente tabla muestra los pines de interrupción que posee cada placa de arduino:
Столеро | Сосны наперстянки пригодные для использования на перерывах |
---|---|
Uno, Nano, Mini, otros basados en 328 | 2, 3 |
Uno WiFi Rev.2, nano cada | todos los pines digitales |
Мега, Мега2560, МегаАДК | 2, 3, 18, 19, 20, 21 |
Micro, Leonardo, otro basado en 32u4 | 0, 1, 2, 3, 7 |
Серо | todos los pines digitales, кроме 4 |
Tableros de la familia MKR | 0, 1, 4, 5, 6, 7, 8, 9, А1, А2 |
Нано 33 Интернет вещей | 2, 3, 9, 10, 11, 13, 15, А5, А7 |
Nano 33 BLE, Nano 33 BLE Sense | тодос лос пайнс |
Дебидо | todos los pines digitales |
101 | Todos los pines digitales (только сосны 2, 5, 7, 8, 10, 11, 12, 13 с функцией CHANGE) |
Acerca de las rutinas de servicio de interrupción
Los ISR son types especiales de funciones que tienen algunas limitaciones únicas que la mayoría de las otras funciones no tienen. Un ISR нет puede tener ningún parametro, y no debe devolver nada.
В целом, ISR debe ser lo más corto y rápido posible. Si su programa usa múltiples ISR, solo uno puede ejecutarse a la vez, otras interrupciones se ejecutarán después de que finalice la fact en un orden que depende de la Prioridad que tengan. миллис ()
се basa en las interrupciones para contar, por lo que nunca se incrementará dentro de un ISR. Dado que delay()
requiere interrupciones para funcionar, no funcionará si se llama dentro de un ISR. Функциональная micros()
Первоначальная компенсация за счет исправления ошибочного поведения в течение 1–2 мс. delayMicroseconds()
не используется, если он не используется, для нормальной работы.
В общем, глобальные переменные используются для передачи данных между ISR и основной программой. Para asegurarse де que las переменные compartidas entre un ISR y el programa main se Actualicen Correctamente, объявляют como volatile.
Номер прерывания
Normalmente debería usar digitalPinToInterrupt(pin)
, в котором указан номер прерывания, направляемый в систему. Los pines específicos con interrupciones y su número de mapeo a interrupción varían para cada tipo de placa. El uso directo де números де interrupción puede parecer simple, pero puede causar Problemas де compatibilidad cuando su programa se ejecuta en una placa diferente.
Синтаксис
attachInterrupt(digitalPinToInterrupt(pin), ISR, режим) //рекомендуется attachInterrupt(interrupt, ISR, mode) // не рекомендуется attachInterrupt(pin, ISR, mode) //(Не рекомендуется. Además, esta sintaxis single funciona en las placas SAMD Arduino, Uno //WiFi Rev2, до 101.)
Параметры
- прерывание
- Номер прерывания. Tipos de datos Permitidos: внутр.
- pin
- Номер контакта Arduino.
- ISR
- El ISR a llamar cuando se произвести ла прерывание; Esta función no debe tomar parametros y no devolver nada.