Arduino:Справочник языка Arduino/Функции/Внешние прерывания/attachInterrupt()

Материал из Онлайн справочника
Перейти к: навигация, поиск

{{#setlogo:ArduinoCommunityLogo.png}}

Перевод: Максим Кузьмин (Cubewriter)
Перевел 1887 статей для сайта.

Контакты:

Проверка/Оформление/Редактирование: Мякишев Е.А.


Функция[1]

attachInterrupt()

Описание

Первый параметр для функции attachInterrupt — это номер прерывания. Для того, чтобы присвоить этот параметр тому или иному цифровому контакту, как правило, используется функция digitalPinToInterrupt(pin). Например, для подключения к 3-ему контакту в первый параметр функции нужно вписать digitalPinToInterrupt(3).

Плата Цифровые контакты, которые могут использовать прерывания
Uno, Nano, Mini и другие на базе 328 2, 3
Mega, Mega2560, MegaADK 2, 3, 18, 19, 20, 21
Micro, Leonado и другие на базе 32u4 0, 1, 2, 3, 7
Zero Все, за исключением 4
Due Все

Примечание

Внутри этой функции не будет работать функция delay() и не будет увеличиваться значение от функции millis(). Кроме того, последовательные данные, посылаемые во время работы этой функции, могут быть утеряны. Также все переменные, которые будут модифицированы внутри этой функции, нужно объявлять как volatile. Более подробно об этом читайте ниже — в разделе об ISR.

Использование прерываний

Прерывания применяются, к примеру, в микроконтроллерных программах — когда вам нужно сделать так, чтобы те или иные процессы выполнялись автоматически. Кроме того, они могут помочь в решении проблем с синхронизацией. Что касается конкретных областей применения, то прерывания могут пригодиться, например, при считывании данных с поворотного регулятора или отслеживания пользовательских данных.

Написать программу, которая постоянно, не упуская ни единого импульса, следила бы за линией, ведущей от поворотного регулятора, и в то же время занималась чем-нибудь еще, не так-то просто. Похожая ситуация обстоит и с другими датчиками — к примеру, со звуковым сенсором, который следит за кликами мышью, или с инфракрасным сенсором (фотопрерывателем), который пытается уловить какое-либо движение (например, падение монеты). Тут-то на помощь и приходит прерывание — оно позволяет сделать так, чтобы микроконтроллер, с одной стороны, продолжал следить за какими-либо сигналами (движениями, звуками и т.д.), а с другой, мог выполнять какую-то другую работу.

Об ISR

ISR (т.е. Interrupt Service Routines, что можно перевести как «обработчик прерываний») — это особый вид функций, имеющих ряд уникальных ограничений, которых нет у других функций. Они не могут иметь никаких параметров и не возвращают никаких данных.

ISR должны быть как можно более короткими и быстрыми. Если в вашем скетче используется несколько ISR, одновременно можно запустить лишь одну, а другие будут выполнятся после — в зависимости от имеющегося приоритета. Счетчик в функции millis() полагается на прерывания, поэтому внутри ISR работать не будет. Поскольку функции delay() для работы тоже требуются прерывания, внутри ISR она тоже работать не будет. Функция micros() первое время будет работать нормально, но спустя 1-2 миллисекунды начнутся перебои. Функции delayMicroseconds() счетчик не требуется, поэтому она будет работать в нормальном режиме.

Как правило, для передачи данных между ISR и главной программой используются глобальные переменные. Для того, чтобы изменение переменных, используемых в ISR и главной программе, выполнялось корректно, их нужно объявлять как volatile.

Более подробно о прерываниях можно почитать в заметках Ника Гаммона.

Синтаксис

Рекомендуется — attachInterrupt(digitalPinToInterrupt(pin), ISR, mode)
Не рекомендуется — attachInterrupt(interrupt, ISR, mode)
Не рекомендуется (только для Due, Zero) — attachInterrupt(pin, ISR, mode)

Параметры

interrupt — номер прерывания (int)
pin — номер контакта (только для Due, Zero)
ISR — ISR, которая будет вызываться при возникновении прерывания; у этой функции не должно быть параметров и, к тому же, она не должна ничего возвращать; кроме того, иногда эту функцию также называют «обработчиком прерываний»
mode — определяет, когда должно сработать прерывание; работает, как правило, с четырьмя константами:

LOW — прерывание срабатывает, когда контакт переключается в значение LOW
CHANGE — прерывание срабатывает, когда значение контакта меняется
RISING — прерывание срабатывает, когда контакт переключается из LOW в HIGH
FALLING — прерывание срабатывает, когда контакт переключается из HIGH в LOW
HIGH (только для Due, Zero) — прерывание срабатывает, когда контакт переключается в HIGH

Что возвращает

Ничего.

Пример

  1. int pin = 13;
  2. volatile int state = LOW;
  3.  
  4. void setup() {
  5.     pinMode(pin, OUTPUT);
  6.     attachInterrupt(digitalPinToInterrupt(pin), blink, CHANGE);
  7. }
  8.  
  9. void loop() {
  10.     digitalWrite(pin, state);
  11. }
  12.  
  13. void blink() {
  14.     state = !state;
  15. }

Номера прерывания

Как правило, номер прерывания нужно указывать в скетче не напрямую, а при помощи digitalPinToInterrupt(pin). Контакты для прерываний, а также присвоение номеров прерываний к определенным контактам на разных платах может варьироваться. Прямое использование номеров прерывания лишь на первый взгляд кажется простым, но если запустить ваш скетч на другой плате, это может привести к проблемам с совместимостью.

Тем не менее, на старых скетчах часто используются как раз прямые номера прерываний — как правило, номер «0» (для 2-ого цифрового контакта) и номер «1» (для 3-его цифрового контакта). Эта таблица показывает, какие контакты для прерываний имеются у разных плат Arduino:

Плата Ном. «0» Ном. «1» Ном. «2» Ном. «3» Ном. «4» Ном. «5»
Uno, Ethernet 2 3
Mega2560 2 3 21 20 19 18
Платы на базе32u4 (Leonardo, Micro и пр.) 3 2 0 1 7
Due, Zero см. ниже

На плате Arduino Uno функцию для прерывания можно применить ко всем доступным контактам. Номер контакта можно указать в attachInterrupt() напрямую.

На плате Arduino Zero функцию для прерывания можно применить ко всем доступным контактам, кроме 4-ого. Номер контакта можно указать в attachInterrupt() напрямую.

См.также

  1. detachInterrupt

Внешние ссылки

  1. attachInterrupt()