Подписаться на получение новых статей на почту:

Подключаем кнопки к AVR. Шаг №12

Обновлено 14.05.15. Здравствуйте дорогие друзья. В этой статье пойдет речь о кнопках и методе борьбы с дребезгом. В прошлой статье я рассказывал о первом своем устройстве —  анализаторе, где были применены кнопки, поэтому пора рассмотреть тонкости их работы. Материала в интернете куча, но каждый индивидуальный взгляд на решение вопроса увеличивает скорость понимания данного направления. Поэтому я и решил написать. Ну что ж перейдем к кнопкам. Зачем нужны кнопки? К примеру вы создаете тот же барьер — реле напряжения, но для гибкости устройства необходимо менять граничные уровни напряжения, т.к. сеть у каждого очень индивидуальна, к сожалению. Вот тут и приходят на помощь кнопки.

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

В основном применяют не фиксирующиеся нормально разомкнутые, но это решение строго личное , что и как использовать. Я дальше буду писать про нормально разомкнутые. Подключить кнопку к микроконтроллеру AVRКнопки для AVR, очень просто на рисунке ниже представлена схема подключения. В данном случае, просто подсоединяем один конец к ножке МК, а второй вывод к земле либо к питанию. Не забываем задействовать внутренний подтягивающий резистор для исключения помех от наводок, даже тем же пальцем. Принцип следующий настраиваем порт как вход т.е. регистр DDRx выставляем в 0, далее подтягиваем внутренние резисторы, т.е. выставляет регистр PORTx в1.

Подключение кнопок к AVR А далее алгоритм опроса, вот здесь он может быть очень индивидуален, ну во первых если нам необходимо  просто ввести данные вначале программы и далее кнопки недолжны реагировать, то тут можно поместить опрос в циклическое условие, например ниже представлен кусочек кода моей программы на СИ для двух кнопок. 

while ((e == 0)&&(e1 == 0)) //  Начало цикла, берем любые переменные, к примеру равные нулю
        // Далее начинается обработка кода, пока не поменяется, хотя бы одно значение переменной на истинно
         {
   if ((PIND & 0×20) == 0) // здесь мы нажали на кнопку, и в данном случае на пине 5 порта установился 0. Ниже небольшой код по обработке дребезга контактов, о нем написал чуть ниже.
   {
                   _delay_ms (50);         // Устранение дребезга клавиш
                   if ((PIND & 0×20) == 0) // Опять проверяем нажатие
                      e++;             //Увеличиваем на 1
                      ……     ;          // Здесь выполняется необходимая нам команда
                   while ((PIND & 0×20) == 0) //Все ждем отпускание кнопки
                          {}
}  // Выходим из условия
  else {}; //можно и неиспользовать, пустая комманда, даже занимающая сокото там тактов
              if ((PIND & 0×40) == 0) // а здесь мы нажал на кнопку с2, ну и т.д.
               {
                      _delay_ms (50);
                       if ((PIND & 0×40) == 0)
                      e1++;
                      ……;
                      while ((PIND & 0×40) == 0)
                      {}
               }
               else {};
             ……;
 }; // выходим из циклического условия если мы нажали хотя бы одну кнопку

Данный код представляет примерный подход опроса двух кнопок. Алгоритм может меняться как пожелает фантазия. Но самое главное что в коде опроса должен присутствовать антидребезговый код. Что это? Дребезг это явление возникает в переключателях, которое представляет собой в момент переключения случайные многократные неконтролируемые замыкания и размыкания контактов и длятся они от десятков до сотен миллисекунд. На рисунке ниже у нас пример дребезга. Т.к. в протеусе все Дребезг кнопокидеально, то пришлось дорисовать реальность – дребезг красным. Что у нас получается, МК посчитает, перед переходом на другую команду в момент переключения кнопки любое состояние из полосы неопределенности 0 или 1 которая возникает при  колебаниях за счет дребезга контактов. Т.е. выходит угадал не угадал… Техника требует точности. Борются двумя методами, первый для компенсации дребезга применяют переключатели с обратной связью, с характеристикой в виде прямоугольной петли гистерезиса и т. д., второй программный метод. Этот метод мы  и рассмотрим . В коде выше есть комментарий //Устранение дребезга клавиш. к строке _delay_ms (50); я взял 50 мс, но для пущей уверенности можно и сто а вообще надо подстраиваться под свою разработку. В коде после задержки, когда колебания затухли, опять сравнивается состояние. Вот таким нехитрым методом происходит опрос кнопок.

Давайте рассмотрим случай когда кнопка должна использоваться на протяжении всего времени  работы устройства. Здесь нам на помощь приходят прерывания, например их можно использовать внешнее прерывание. К примеру подключаем кнопку к выводу INT0, другой вывод  к земле, здесь зависит от определения условий генераций внешних прерывания и от типа МК. Читайте даташит. Порт также настраиваем на вход, подтягиваем резистор. В нормальном состоянии, когда кнопка разомкнута на выводе присутствует 1. В момент замыкания на вывод приходит 0, где по спадающему фронту (настройка) запускается обработчик прерываний. Для запуска внешнего прерывания необходимо флаг I регистра SREG установить в 1. При возникновения прерывания этот флаг аппаратно сбрасывается. Если мы хотим вызывать вложенные прерывания то необходимо программно установить этот флаг. При выходе из обработчика необходимо выполнить комманду reti; , которая установит этот флаг в 1. Например в программе считывания кнопок на АЦП был описан способ считывания кнопок в прерывании, только уже используя АЦП.

Ниже приведен код для работы с внешним прерыванием.

GICR =0×40; //Управляющий регистр для разрешения/запрещения  прерываний. Разрешаем внешние прерывание INT0.
MCUCR = 0×02; //Конфигурационный регистр для выбора условий генераций внешнего прерывания. По спадающему фронту.
sei (); //установка флага I регистра SREG в 1. Разрешение общего прерывания. Должен быть обязательно установлен.
SIGNAL (SIG_INTERRUPT0)//Обработчик прерывания по вектору внешнего прерывания. Данные векторы хорошо описаны в Шпаке для среды WinAVR.
//Здесь  пишем необходимый нам код при нажатии на кнопку   }
//Далее обработчик прерывания заканчивает свою работу, и программа возвращается в основной цикл.

Также наверное стоит упомянуть о регистре GIFR, флаги которого используются для индикации прерываний. Кому необходимо читаем даташит.Способов использования прерываний для кнопок куча, поэтому читаем, подбираем… На этом все. В следующей статье поговорим об использовании памяти EEPROM. Всем пока.

Просмотрено 34326 раз.

Я на Google+

Подключаем кнопки к AVR. Шаг №12: 12 комментариев

  1. Спасибо за статью, кратко и ясно. Еще бы проектик в протеусе для наглядности.

    • Здравствуйте. Да есть проектик в статье№33 , там правда обработка кнопок в ацп, но всеравно сходство есть. А также в статье №26 обработка сдвига синусоиды, там правда только проект без исходника,но для наглядности самый раз.

  2. Здравствуйте, если задам несколько вопросов по кнопкам сможете мне ответить.

  3. Вот смотрите вы пишите про опрос кнопок в цикле, я с вами согласен. Я так делал получал хороший отклик на нажатие кнопки. Насчет введения антидребезга не знаю. Пробовал делал с ним и без него разницы я не увидел. Вопрос в следующем. Как модернизировать программу в цикле, чтобы переменная увеличивалась быстрее, если держать кнопку постоянно, то есть время делай должно сокращаться. И наоборот, если нажимаешь кнопку через определенное время, просто отклик на каждое нажатие, время delay опять принимает определенное значения. Я пробовал экспериментировал с delay, но насколько я понял эта функция требует записи числа. А изменяемый аргумент вписать в нее нельзя.

    • Я думаю в цикле ожидания отпускания кнопки можно прописать алгоритм с еще одной проверкой, что кнопка нажата уменьшить время задержки поставить счетчик и вот Вам будет быстрое увеличение переменной.

  4. и второй вопрос чисто практический нужна кнопка для установки в корпус, но максимально плоская и небольшая. Я нашел одну pbs28b, но она великовата. У нее диаметр 22 мм. Может где то вам попадалось что то подобное но поменьше.

  5. void time_min (void) // установка минут

    {

    unsigned char c, min, min_1, j, vuxod;

    for (c = 0; c 59)

    {

    j=0;

    }

    min=j;

    min_1=j;

    digit_1 = min / 10; //отображение на дисплее

    min -= digit_1*10;

    digit_0 = min;

    _delay_ms (300);

    if ((PINC&0×02)!=0×00) //кнопка отжата

    {

    vuxod++; //увеличиваем переменную для досрочного выхода из цикла

    }

    if (vuxod>20)

    {

    SetMinutes (min_1); //записываем минуты в микросхему времени

    return; //досрочный выход из цикла

    }

    //SetMinutes (min_1);

    }//for

    }//time_min

    Написал кусок кода здесь как бы немного другая задача, нужно при отжатой кнопки заранее выходить из цикла. Применил оператор return, пробовал также break но ни с одним из них не работает. Можете бегло глянуть что не так.

  6. Хотя вроде бы я разобрался с последним вопросом. Надо выход из цикла писать break а потом еще в самом конце return это выход из функции. Так работает.

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

Ваш e-mail не будет опубликован.

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Subscribe without commenting