4.06. Аппаратные прерывания.md
До сих пор все наши программы работали последовательно. Внутри бесконечного цикла loop() микроконтроллер неустанно проверял условия одно за другим: «Нажата ли кнопка? А сейчас? А теперь?». Такой метод называется опросом (polling), и он похож на то, как если бы вы каждые пять минут подбегали к почтовому ящику в ожидании письма. Это работает, но отнимает всё ваше время и внимание. А что, если письмо придёт и его тут же заберут, пока вы отвернулись? Вы его пропустите.
Точно так же и микроконтроллер может пропустить короткое событие (например, быстрое нажатие кнопки), если в этот момент он был занят выполнением delay() или сложными вычислениями. Чтобы решить эту проблему, существует гораздо более элегантный и эффективный механизм — аппаратные прерывания.
Принцип работы прерываний
Представьте, что вы оставили курьеру записку: «Когда прибудет посылка, не клади её в ящик, а позвони в дверь». Теперь вы можете спокойно заниматься своими делами: читать книгу, готовить, смотреть фильм. Как только курьер нажмёт на кнопку звонка, вы немедленно отложите свои дела, откроете дверь, заберёте посылку и вернётесь к своему занятию ровно с того места, на котором остановились.
Аппаратное прерывание работает точно так же. Вы «говорите» микроконтроллеру: «Следи за этим пином. Как только на нём изменится сигнал, немедленно приостанови loop(), выполни вот эту специальную короткую функцию и вернись обратно».
Это даёт два огромных преимущества: 1. Мгновенная реакция - микроконтроллер реагирует на событие сразу же, а не когда до него дойдёт очередь в loop(). 2. Эффективность - процессор не тратит время на постоянные проверки, а может заниматься другими полезными задачами.

Прерывания на плате Рудирон
На плате Рудирон некоторые пины специально предназначены для работы с аппаратными прерываниями. Как мы видим из документации и схемы, это пины 31, 32 и 35. Удобно, что именно к этим пинам подключены встроенные кнопки B2, B3 и B1 соответственно. Это позволяет нам экспериментировать с прерываниями без подключения внешних компонентов.
Настройка прерываний - attachInterrupt()
Чтобы «повесить» прерывание на пин, используется функция attachInterrupt(). Её обычно вызывают один раз в setup().
Синтаксис функции:
attachInterrupt(digitalPinToInterrupt(номерПина), ISR, режим);
Давайте разберём каждый параметр: 1. digitalPinToInterrupt(номерПина). Это важная функция-помощник. Она преобразует обычный номер пина (например, 35) в специальный номер прерывания, понятный микроконтроллеру. Всегда используйте её, чтобы указать, какой пин будет источником прерывания. 2. ISR (Interrupt Service Routine). Это имя вашей функции, которая будет вызвана при срабатывании прерывания. Её также называют обработчиком прерывания. Это должна быть функция, которая не принимает аргументов и ничего не возвращает (void myFunction()). 3. режим: Указывает, на какое именно изменение сигнала должен реагировать микроконтроллер: * LOW - прерывание срабатывает, пока на пине удерживается низкий уровень. * CHANGE - при любом изменении уровня (с LOW на HIGH или с HIGH на LOW). * RISING - при переходе с LOW на HIGH (передний фронт импульса). * FALLING - при переходе с HIGH на LOW (задний фронт импульса).
Чтобы отключить прерывание, используется функция detachInterrupt(digitalPinToInterrupt(номерПина)).
Золотые правила написания обработчика прерываний (ISR)
Функция-обработчик прерывания — особенная. Во время её выполнения весь остальной мир для микроконтроллера замирает. Поэтому при её написании нужно соблюдать несколько строгих правил: 1. Делайте её максимально короткой и быстрой. loop() ждёт! Внутри ISR обычно только меняют значение переменной (устанавливают флаг), а все долгие действия выполняют в loop(). 2. Не используйте delay() и delayMicroseconds(). Эти функции зависят от таймеров, которые отключаются во время прерывания. 3. Будьте осторожны с Serial. Отправка данных по Serial тоже зависит от прерываний и может работать некорректно или привести к потере данных. Лучше установить флаг в ISR, а вывести данные в loop(). 4. Используйте volatile. Если вы используете переменную и в ISR, и в loop(), её нужно объявить с ключевым словом volatile. Например: volatile bool flag = false;. Это говорит компилятору, что переменная может измениться в любой момент (из-за прерывания), и он не должен кэшировать её значение, а всегда считывать из памяти.
Пример (включение/выключение встроенного светодиода L1 по нажатию кнопки B1):
// Используем встроенные имена для пинов
// BUTTON_BUILTIN_1 соответствует пину 35, который поддерживает прерывания
// LED_BUILTIN_1 соответствует пину 5
// Эта переменная будет изменяться в прерывании, поэтому она volatile
volatile bool ledState = LOW;
void setup() {
pinMode(LED_BUILTIN_1, OUTPUT);
pinMode(BUTTON_BUILTIN_1, INPUT_PULLDOWN);
// Настраиваем прерывание. При нажатии кнопки сигнал на пине станет высоким (RISING)
attachInterrupt(digitalPinToInterrupt(BUTTON_BUILTIN_1), toggleLed, RISING);
Serial.begin(9600);
Serial.println("Система готова. Нажмите кнопку B1, чтобы изменить состояние светодиода L1.");
}
void loop() {
// Основной цикл просто обновляет состояние светодиода на основе значения переменной ledState
digitalWrite(LED_BUILTIN_1, ledState);
// Здесь может быть любой другой код, и он не будет мешать реакции на кнопку.
}
// Это наш обработчик прерывания (ISR).
// Название может быть любым, главное — чтобы оно совпадало с тем, что мы указали в attachInterrupt
void toggleLed() {
// Инвертируем состояние светодиода
ledState = !ledState;
}
В этом примере loop() просто устанавливает состояние светодиода. При каждом нажатии на кнопку B1 мгновенно срабатывает прерывание и вызывается функция toggleLed(), которая меняет значение флага ledState. В следующем цикле loop() светодиод изменит своё состояние. Всё происходит мгновенно, и основной цикл не тратит время на проверку кнопки.
Зачем это нужно?
Аппаратные прерывания — это фундаментальный инструмент для создания отзывчивых и эффективных систем. Они незаменимы, когда нужно:
- Мгновенно реагировать на важные сигналы (например, кнопка аварийной остановки).
- Считать быстрые импульсы от энкодеров или датчиков скорости, не пропуская ни одного.
- Декодировать сигналы от пультов дистанционного управления.
- «Пробуждать» микроконтроллер из режима сна для экономии энергии.
Поздравляем с освоением прерываний! Теперь ваши проекты могут стать по-настоящему быстрыми и эффективными. Если вы хотите применить эти знания на практике, переходите к лабораторным работам, чтобы создать по-настоящему многозадачное устройство. А если вы готовы изучить ещё один способ заставить Рудирон делать несколько дел одновременно, но уже чисто программным методом, отправляйтесь в следующий параграф, где мы познакомимся с функцией millis().
- Страницы
- 1. Введение
- 1.01. Лабораторная работа №1.1
- 1.02. Лабораторная работа №1.2
- 1.03. Лабораторная работа №1.3
- 1.04. Лабораторная работа №1.4
- 1.05. Лабораторная работа №1.5
- 2. Основы электроники
- 2.01. Электрический ток и параметры цепи
- 2.01.1. Лабораторная работа №2.1.1
- 2.01.2. Лабораторная работа №2.1.2
- 2.02. Сопротивление в цепи
- 2.02.1. Лабораторная работа №2.2.1
- 2.02.2. Лабораторная работа №2.2.2
- 2.03. Полупроводники
- 2.03.1. Лабораторная работа №2.3.1
- 2.03.2. Лабораторная работа №2.3.2
- 3. Основы программирование на C++
- 3.01. Типы данных и переменные
- 3.01.1. Практикум
- 3.02. Операторы в C++
- 3.02.1. Практикум
- 3.03. Структуры ветвления
- 3.03.1. Практикум
- 3.04. Структуры повторения
- 3.04.1. Практикум
- 3.05. Массивы
- 3.05.1. Практикум
- 3.06. Функции
- 3.06.1. Практикум
- 3.07. Решения задач
- 4. Программирование микроконтроллеров
- 4.01. Цифровые сигналы и GPIO
- 4.01.1. Лабораторная работа №4.1.1
- 4.01.2. Лабораторная работа №4.1.2
- 4.01.3. Лабораторная работа №4.1.3
- 4.01.4. Лабораторная работа №4.1.4
- 4.01.5. Лабораторная работа №4.1.5
- 4.01.6. Лабораторная работа №4.1.6
- 4.01.7. Лабораторная работа №4.1.7
- 4.01.8. Лабораторная работа №4.1.8
- 4.02. Аналоговые сигналы и ШИМ
- 4.02.1. Лабораторная работа №4.2.1
- 4.02.2. Лабораторная работа №4.2.2
- 4.02.3. Лабораторная работа №4.2.3
- 4.02.4. Лабораторная работа №4.2.4
- 4.02.5. Лабораторная работа №4.2.5
- 4.03. Аналоговый сигнал и АЦП
- 4.03.1. Лабораторная работа №4.3.1
- 4.03.2. Лабораторная работа №4.3.2
- 4.03.3. Лабораторная работа №4.3.3
- 4.03.4. Лабораторная работа №4.3.4
- 4.03.5. Лабораторная работа №4.3.5
- 4.04. Аналоговый сигнал и ЦАП
- 4.04.1. Лабораторная работа №4.4.1
- 4.04.2. Лабораторная работа №4.4.2
- 4.05. Генерация и измерение импульсов
- 4.05.1. Лабораторная работа №4.5.1
- 4.05.2. Лабораторная работа №4.5.2
- 4.06. Аппаратные прерывания
- 4.06.1. Лабораторная работа №4.6.1
- 4.06.2. Лабораторная работа №4.6.2
- 4.07. Псевдопараллелизм
- 4.07.1. Лабораторная работа №4.7.1
- 4.07.2. Лабораторная работа №4.7.2
- 4.08. Интерфейсы связи - UART
- 4.08.1. Лабораторная работа №4.8.1
- 4.09. Интерфейсы связи - I2C
- 4.09.1. Лабораторная работа №4.9.1
- 4.10. Интерфейсы связи - SPI
- 4.10.1. Лабораторная работа №4.10.1
- home
-
imgs
- 1. Введение
- 1.01. Лабораторная работа №1.1
- 1.02. Лабораторная работа №1.2
- 1.03. Лабораторная работа №1.3
- 1.04. Лабораторная работа №1.4
- 1.05. Лабораторная работа №1.5
- 2. Основы электроники
- 2.01. Электрический ток и параметры цепи
- 2.01.1. Лабораторная работа №2.1.1
- 2.01.2. Лабораторная работа №2.1.2
- 2.02. Сопротивление в цепи
- 2.02.1. Лабораторная работа №2.2.1
- 2.02.2. Лабораторная работа №2.2.2
- 2.03. Полупроводники
- 2.03.1. Лабораторная работа №2.3.1
- 2.03.2. Лабораторная работа №2.3.2
- 3. Основы программирование на C++
- 3.01. Типы данных и переменные
- 3.01.1. Практикум
- 3.02. Операторы в C++
- 3.02.1. Практикум
- 3.03. Структуры ветвления
- 3.03.1. Практикум
- 3.04. Структуры повторения
- 3.04.1. Практикум
- 3.05. Массивы
- 3.05.1. Практикум
- 3.06. Функции
- 3.06.1. Практикум
- 3.07. Решения задач
- 4. Программирование микроконтроллеров
- 4.01. Цифровые сигналы и GPIO
- 4.01.1. Лабораторная работа №4.1.1
- 4.01.2. Лабораторная работа №4.1.2
- 4.01.3. Лабораторная работа №4.1.3
- 4.01.4. Лабораторная работа №4.1.4
- 4.01.5. Лабораторная работа №4.1.5
- 4.01.6. Лабораторная работа №4.1.6
- 4.01.7. Лабораторная работа №4.1.7
- 4.01.8. Лабораторная работа №4.1.8
- 4.02. Аналоговые сигналы и ШИМ
- 4.02.1. Лабораторная работа №4.2.1
- 4.02.2. Лабораторная работа №4.2.2
- 4.02.3. Лабораторная работа №4.2.3
- 4.02.4. Лабораторная работа №4.2.4
- 4.02.5. Лабораторная работа №4.2.5
- 4.03. Аналоговый сигнал и АЦП
- 4.03.1. Лабораторная работа №4.3.1
- 4.03.2. Лабораторная работа №4.3.2
- 4.03.3. Лабораторная работа №4.3.3
- 4.03.4. Лабораторная работа №4.3.4
- 4.03.5. Лабораторная работа №4.3.5
- 4.04. Аналоговый сигнал и ЦАП
- 4.04.1. Лабораторная работа №4.4.1
- 4.04.2. Лабораторная работа №4.4.2
- 4.05. Генерация и измерение импульсов
- 4.05.1. Лабораторная работа №4.5.1
- 4.05.2. Лабораторная работа №4.5.2
- 4.06. Аппаратные прерывания
- 4.06.1. Лабораторная работа №4.6.1
- 4.06.2. Лабораторная работа №4.6.2
- 4.07. Псевдопараллелизм
- 4.07.1. Лабораторная работа №4.7.1
- 4.07.2. Лабораторная работа №4.7.2
- 4.08. Интерфейсы связи - UART
- 4.08.1. Лабораторная работа №4.8.1
- 4.09. Интерфейсы связи - I2C
- 4.09.1. Лабораторная работа №4.9.1
- 4.10. Интерфейсы связи - SPI
- 4.10.1. Лабораторная работа №4.10.1
- home