Как НЕ надо делать прерывания на Arduino

Ура, Troyka Slot Shield позволяет подключить Troyka OLED к цифровым выводам (6 и 7, согласно распиновке), а, значит, наконец-то я смог реализовать вызов прерываний. Но, как оказалось, все не так просто, как пишут в документации на форуме Arduino. Спойлер: если в функции-обработчике прерываний вызвать любую другую функцию, задействующую системные прерывания (в том числе, кстати, и замер миллисекунд, millis(), как рекомендуется в документации Arduino) — то результат будет примерно вот таким:

А вот как на самом деле это должно было работать:

Под катом — подробное объяснение.

Итак, как это работает.

Сначала загружаем библиотеку дисплея, инициализуирем её и декларируем все пины:

#include <TroykaOLED.h>
// создаём объект для работы с дисплеем
// и передаём I²C адрес дисплея
TroykaOLED myOLED(0x3C);

//Зададим пины кнопок
const byte LEFT_BUTTON = 7;
const byte RIGHT_BUTTON = 6;
//Initializing the button states as 1 (HIGH)
volatile byte left_state = HIGH;
volatile byte right_state = HIGH;

Обратите внимание на декларацию volatile — именно она поясняет компилятору, что данный параметр будет изменяться во время обработки прерываний.

Далее, необходимо определить функции обработки прерываний. У нас их две, для левой и правой кнопки, и в обоих мы будем читать значение соответствующей переменной:

void rightButtonISR(){
  right_state = digitalRead(RIGHT_BUTTON);
  }

void leftButtonISR(){
  left_state = digitalRead(LEFT_BUTTON);
  }

Внутри setup() стартуем последовательный интерфейс вызовом функции Serial.begin() и добавляем код, подключающий определенные нами функции обработки прерываний к соответствующим пинам с помощью функции attachInterrupt():

void setup() {
  Serial.begin(9600);
  pinMode(RIGHT_BUTTON, INPUT);
  attachInterrupt(RIGHT_BUTTON, rightButtonISR, FALLING);
  pinMode(LEFT_BUTTON, INPUT);
  attachInterrupt(LEFT_BUTTON, leftButtonISR, FALLING);
}

Параметр FALLING определяет срабатывание прерываний при снижении напряжения, снимаемого с кнопки. В зависимости от ваших задач вы можете использовать альтернативные значения этого параметра: LOW (прерывание вызывается при достижении низкого уровня напряжения), CHANGE (прерывание вызывается при любом изменении напряжения), RISING (прерывание вызывается при росте напряжения на входе, к которому присоединена функция прерывания). Внутри основной функции loop() мы уже будем работать с состояниями для левой и правой кнопки, переданными нам из обработчиков прерываний (где мы вызывали процедуру digitalRead()):

void loop() {
  if (right_state != HIGH)
  {
    //тут должен быть ваш код, что-то делающий, когда нажата правая кнопка
    right_state = HIGH;

    //возвращаем состояние кнопки в исходное значение
    }
  if (left_state != HIGH)
  {
    //код, что-то делающий после нажатия левой кнопки
    left_state = HIGH;
    //возвращаем состояние кнопки в исходное значение
    }
}

Ну вот и все! Удачных вам поделок.

Полный код скетча из видео доступен тут.

З.Ы. Как оказалось, разработчики Curie не стали утруждать себя написанием библиотеки HID.h для работы с устройствами ввода, поэтому следующий пост будет уже на другой платформе.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *