Обработка нажатия кнопки в прерывании

В статье про кнопку был рассмотрен программный метод подавления дребезга. Для обработки факта нажатия/отпускания кнопки так же можно использовать прерывания. Преимущества такого способа — в отсутствии необходимости в программе постоянно контролировать уровень сигнала на входе, к которому подключена кнопка.key_k

Для отработки состояния кнопки в прерывании нужно определить процедуру обработки и подключить ее в качестве обработчика аппаратного прерывания по какому-нибудь входу (для Arduino UNO — это pin2 (Int0) или pin3 (Int1).

#define p_Sw 2  //вход для кнопки (Int0) pin2
#define t_Dreb 50  //интервал для устраниения дребезга (мс)

unsigned int n_Key = 0;   //считаем число нажатий на кнопку
int t_Tek = 0;    //текущий отсчет времени при определении нажатия
int t_Pred = 0;   //предыдущий отсчет
int t_T1 = 0;     //длительность отсутствия реакции на кнопку
int pin_Tek = 1;  //состояние кнопки (0 - замкнута)

void setup() { 
  Serial.begin(9600);  
  pinMode(p_Sw, INPUT_PULLUP); //вход с внутр.резистором на VCC
  attachInterrupt(0, pressK, CHANGE);  //кнопка на Int0 (pin2)
}

void loop() {
  Serial.println(n_Key);
  delay(2000);
}

void pressK()  //обработка прерывания от кнопки (Int0)
{
   pin_Tek = digitalRead(p_Sw); //читаем текущее состояние pin2 (Int0)
   t_Tek = millis(); //текущий отсчет времени
   if (t_Tek > t_T1) {//если время подавления дребезга не прошло - игнорируем
        if (pin_Tek == 0) { //замкнуто
            n_Key ++; //подсчет числа нажатий
            t_Pred = t_Tek; //начало для определения след.периода
       }
   }
   t_T1 = t_Tek + t_Dreb; //определяем время отсутствия реакции
}

Приведенный пример выводит в последовательный канал состояние переменной n_Key, которая наращивается при каждом нажатии и отпускании кнопки. Кнопка подключена одним контактом к входу прерываний Int0 (pin2 Arduino), а другим — к общему проводу. Функция

attachInterrupt(0, pressK, CHANGE);

назначает процедуру pressK как обработчик прерывания по этому входу (нолик в первом аргументе). CHANGE — означает, что вызов процедуры будет по любому изменению на входе (иные варианты: LOW — по нулю; RISING — по переходу из 0 в 1; FALLING — по спаду из 1 в 0).

Процедура обработки «нечувствительна» к измениям на входе в течение времени t_Dreb (задано 50мс) после первого срабатывания, тем самым «как-бы подавляя дребезг контактов кнопки»).

Надо сказать, что подключение кнопки к входу прерываний — «дурной тон». Слишком уж непредсказуем дребезг контактов: процедура может быть вызвана слишком большое число раз :(. Но в не слишком ответственных системах можно поступить и так. Этот метод использован в конструкции велоспидометра

Обработка нажатия кнопки в прерывании: 2 комментария

  1. Когда Вы вызываете прерывание , у Вас другие прерывание запрещены! и мы не можем получить адекватность данных от фун. millis () таким способом от дребезга не избавиться. тем паче Вы вызываете прерывание 0 которое как раз отвечает за таймер 0 , если я правильно думаю.

    1. Вызываемое прерывание никак не связано с таймером 0. Millis() просто считывает значение наращиваемой в прерывании от таймера переменной — так что значение времени будет актуальным («щелочка» для прерывания от таймера всегда найдется).
      Упоминаемая статья в Радио описывает велоспидометр, где использован такой подход — устройство рабочее и показывает адекватные результаты (а статья даже получила поощрительный приз среди лучших в 2015 году 🙂

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