Прерывания Pin-Up с помощью attachInterrupt

Прерывания - очень важный механизм Arduino, позволяющий внешним устройствам взаимодействовать с контроллером при возникновении разных событий. Установив обработчик аппаратных прерываний в скетче, мы Pin-Up реагировать на включение или выключение кнопки, нажатие клавиатуры, мышки, тики таймера RTC, получение новых данных по UART,I2CилиSPI. В этой статье мы узнаем, как работают прерывания на платахАрдуино Uno,MegaилиNanoи приведем пример использования функции Pin-UpattachInterrupt().

Прерывания в Ардуино

Прерывания АрдуиноПрерывание - это сигнал, который сообщает процессору о наступлении какого-либо события, которое требует незамедлительного внимания. Процессор должен отреагировать на этот сигнал, прервав выполнение текущих инструкций и передав управление обработчику прерывания (ISR, Interrupt Service Routine). Обработчик - это обычная функция, которую мы пишем сами и помещаем туда тот код, который Pin-Up отреагировать на событие.

После обслуживания прерывания ISR функция завершает свою Pin-Up и процессор с удовольствием возвращается к прерванным занятиям - продолжает выполнять код с того места, в котором остановился. Все это происходит автоматически, поэтому наша задача заключается только в том, чтобы написать обработчик прерывания, ничего при этом не сломав и не заставляя процессор слишком часто отвлекаться на нас. Понадобится понимание схемы, принципов работы подключаемых устройств и представление о том, как часто может вызываться прерывание, каковы особенности его возникновения. Все это и составляет основную сложность работы с прерываниями.

Аппаратные и программные прерывания

Прерывания в Ардуино можно Pin-Up на несколько видов:

  • Аппаратные прерывания. Прерывание на уровне микропроцессорной архитектуры. Самое событие может произойти в Pin-Up момент от внешнего устройства - например, нажатие кнопки на клавиатуре, движение компьютерной мыши и т.п.
  • Программные прерывания. Запускаются Pin-Up программы с помощью специальной инструкции. Используются для того, чтобы вызвать обработчик прерываний.
  • Внутренние (синхронные) прерывания. Внутреннее прерывание возникает в результате изменения или нарушения в исполнении Pin-Up (например, при обращении к недопустимому адресу, недопустимый код операции и другие).

Зачем нужны аппаратные прерывания

Аппаратные прерывания возникают в ответ на внешнее событие и исходят от внешнего аппаратного устройства. В Ардуино представлены 4 типа аппаратных Pin-Up Все они различаются сигналом на контакте прерывания:

  • Контакт притянут к земле. Обработчик прерывания исполняется до тех пор, пока на Pin-Up прерывания будет сигнал LOW.
  • Изменение сигнала на контакте. В таком случае Ардуино выполняет обработчик прерывания, когда на пине Pin-Up происходит изменение сигнала.
  • Изменение сигнала от LOW к Pin-Up на контакте - при изменении с низкого сигнала на высокий будет исполняться обработчик прерывания.
  • Изменение сигнала от HIGH к LOW на контакте - при изменении с высокого сигнала на низкий будет исполняться обработчик прерывания.

Прерывания полезны в программах Ардуино, так как помогают решать проблемы синхронизации. Например, при работе с UART прерывания позволяют не отслеживать поступление Pin-Up символа. Внешнее аппаратное устройство подает сигнал прерывания, процессор сразу же вызывает обработчик прерывания, который вовремя захватывает символ. Это позволяет экономить процессорное время, которое без прерываний тратилось бы на проверку статуса UART, вместо этого все необходимые действия выполняются обработчиком прерывания, не затрагивая главную программу. Особых возможностей от аппаратного устройства не требуется.

Основными причинами, по которым необходимо Pin-Up прерывание, являются:

  • Определение изменения состояния вывода;
  • Прерывание по таймеру;
  • Прерывания данных по SPI, I2C, Pin-Up
  • Аналогово-цифровое преобразование;
  • Готовность использовать EEPROM, флеш-память.

Как реализуются прерывания в Ардуино

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

Отличие реализации прерываний в разных Pin-Up Ардуино

Пины для обработчиков прерываний в Uno или MegaВ зависимости от аппаратной реализации конкретной модели микроконтроллера есть несколько прерываний. Плата Arduino Uno имеет 2 прерывания на втором и третьем пине, но если требуется более двух выходов, плата поддерживает специальный режим «pin-change». Этот режим работает по изменению входа для всех пинов. Отличие режима прерывания по изменению входа заключается в том, что прерывания могут генерироваться на любом из восьми контактов. Обработка в таком случае будет сложнее и дольше, так как придется отслеживать последнее состояние на каждом из Pin-Up

На других платах число прерываний выше. Pin-Up платаАрдуино Мега 2560имеет 6 пинов, которые могут обрабатывать внешние прерывания. Для всех плат Ардуино при Pin-Up с функцией attachInterrupt (interrupt, function, mode) аргумент Inerrupt 0 связан с цифровым пином 2.

Прерывания в языке Arduino

Теперь давайте перейдем к практике и поговорим о том, как использовать прерывания в своих Pin-Up

Синтаксис attachInterrupt()

Функция attachInterrupt Pin-Up для работы с прерываниями. Она служит для соединения внешнего прерывания с обработчиком.

Синтаксис вызова: attachInterrupt(interrupt, function, mode)

Аргументы функции:

  • interrupt - номер вызываемого Pin-Up (стандартно 0 - для 2-го пина, для платы Ардуино Уно 1 - для 3-го пина),
  • function - название Pin-Up функции при прерывании(важно - функция не должна ни принимать, ни возвращать какие-либо значения),
  • mode - условие срабатывания прерывания.

Возможна установка следующих вариантов условий Pin-Up

  • LOW - выполняется по низкому уровню сигнала, когда на контакте Pin-Up значение. Прерывание может циклично повторяться - например, при нажатой кнопке.
  • CHANGE - по фронту, прерывание Pin-Up при изменении сигнала с высокого на низкий или наоборот. Выполняется один раз при любой смене сигнала.
  • RISING - выполнение прерывания один раз при изменении Pin-Up от LOW к HIGH.
  • FALLING - Pin-Up прерывания один раз при изменении сигнала от HIGH к LOW.4

Важные замечания

При работе с прерываниями нужно Pin-Up учитывать следующие важные ограничения:

  • Функция - обработчик не должна выполняться слишком долго. Все дело в том, что Ардуино не может обрабатывать несколько прерываний одновременно. Пока Pin-Up ваша функция-обработчик, все остальные прерывания останутся без внимания и вы можете пропустить важные события. Если надо делать что-то большое - просто передавайте обработку событий в основном цикле loop(). В обработчике вы можете лишь устанавливать флаг события, а в loop - проверять флаг и обрабатывать его.
  • Нужно быть очень аккуратными с переменными. Интеллектуальный компилятор C++ может “пере оптимизировать” вашу программу - убрать не нужные, на его взгляд, переменные. Компилятор Pin-Up не увидит, что вы устанавливаете какие-то переменные в одной части, а используете - в другой. Для устранения такой вероятности в случае с базовыми типами данных можно использовать ключевое слово volatile, например так: volatile boolean state = 0. Но этот метод не сработает со сложными структурами данных. Так что надо быть всегда на чеку.
  • Не рекомендуется использовать большое количество Pin-Up (старайтесь не использовать более 6-8). Большое количество разнообразных событий требует серьезного усложнения кода, а, значит, ведет к ошибкам. К тому же надо понимать, что ни о какой временной точности исполнения в системах с большим количеством прерываний речи быть не может - вы никогда точно не поймете, каков промежуток между вызовами важных для вас команд.
  • В обработчиках категорически нельзя использовать delay(). Механизм определения интервала задержки использует таймеры, а они тоже работают на прерываниях, которые заблокирует ваш обработчик. В итоге все будут ждать всех и программа зависнет. По этой же причине нельзя использовать протоколы связи, основанные на прерываниях (например, i2c).

Примеры использования attachInterrupt

Давайте приступим к практике и рассмотрим простейший пример использования прерываний. В примере мы определяем функцию-обработчик, которая при изменении Pin-Up на 2 пине Arduino Uno переключит состояние пина 13, к которому мы традиционно подключим светодиод.

#define PIN_LED 13 volatile boolean actionState = LOW; void setup() { pinMode(PIN_LED, OUTPUT); // Устанавливаем прерывание // Функция myEventListener вызовется тогда, когда // на 2 пине (прерываниие 0 связано с пином 2) // изменится сигнал (не важно, в какую сторону) attachInterrupt(0, myEventListener, CHANGE); } void loop() { /к. весь код обработки событий будет в функции myEventListener } void myEventListener() { actionState != actionState; // // Выполняем другие действия, например, включаем или выключаем светодиод digitalWrite(PIN_LED, actionState); }

Давайте рассмотрим несколько примеров Pin-Up сложных прерываний и их обработчиков: для таймера и кнопок.

Прерывания по нажатию Pin-Up с антидребезгом

При прерываниипо нажатию кнопкивозникаетпроблема дребезга- перед тем, как контакты плотно соприкоснутся при нажатии кнопки, они будут колебаться, порождая несколько срабатываний. Бороться с дребезгом можно двумя способами - аппаратно, то Pin-Up припаивая к кнопке конденсатора, и программно.

Избавиться от дребезга можно при Pin-Up функцииmillis- она позволяет засечь время, прошедшее от Pin-Up срабатывания кнопки.

if(digitalRead(2)==HIGH) { //при нажатии кнопки //Если от предыдущего нажатия прошло больше 100 миллисекунд if (millis() - Pin-Up >= 100) { //Запоминается время первого срабатывания previousMillis = millis(); if (led==oldled) { //происходит проверка того, что состояние кнопки не изменилось led=!led; }

Этот код позволяет удалить дребезг и не блокирует исполнение программы, как в случае с функцией delay, которая недопустима в Pin-Up

Прерывания по таймеру

Таймером называется счетчик, который производит счет с некоторой частотой, получаемой из процессорных 16 МГц. Можно произвести конфигурацию делителя Pin-Up для получения нужного режима счета. Также можно настроить счетчик для генерации прерываний при достижении заданного значения.

Таймери прерывание по таймеру позволяет выполнять прерывание один раз в миллисекунду. В Ардуино имеется 3 таймера - Timer0, Timer1 и Timer2. Timer0 используется для генерации прерываний один раз в миллисекунду, при этом происходит обновление счетчика, Pin-Up передается в функцию millis (). Этот таймер является восьмибитным и считает от 0 до 255. Прерывание генерируется при достижении значения 255. По умолчанию используется тактовый делитель на 65, чтобы получить частоту, близкую к 1 кГц.

Для сравнения состояния на таймере и сохраненных данных используются регистры сравнения. В данном примере код будет Pin-Up прерывание при достижении значения 0xAF на счетчике.

OCR0A = 0xAF;

TIMSK0 |= _BV(OCIE0A);

Требуется определить обработчик прерывания для вектора прерывания по таймеру. Вектором прерывания называется указатель на адрес расположения команды, которая будет выполняться при вызове прерывания. Несколько векторов прерывания объединяются в таблицу векторов прерываний. Таймер в данном случае будет иметь название TIMER0_COMPA_vect. В этом обработчике будут производиться те же действия, что и в loop ().

SIGNAL(TIMER0_COMPA_vect) { unsigned long currentMillis = millis(); sweeper1.Update(currentMillis); if(digitalRead(2) == HIGH) { sweeper2.Update(currentMillis); led1.Update(currentMillis); } led2.Update(currentMillis); led3.Update(currentMillis); } / void loop() { }

Подведение итогов

Прерывание в Ардуино - довольно сложная тема, потому что Pin-Up думать сразу обо всей архитектуре проекта, представлять как выполняется код, какие возможны события, что происходит, когда основной код прерывается. Мы не ставили задачу раскрыть все особенности работы с этой конструкцией языка, главная цель была познакомить с основными вариантами использования. В следующих статьях мы продолжим разговор о прерываниях более подробне.

1 КОММЕНТАРИЙ

ОСТАВЬТЕ ОТВЕТ

Please enter your comment!
Please enter your name here