Матричная клавиатура

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

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

Считывающий порт включается в режиме Pull-up входа, то есть вход с подтягивающими резисторами. Если контроллер это не поддерживает, то эти резисторы надо повесить снаружи.

Сканирующий порт работает в режиме выхода, он подключен к столбцам. Столбцы должны быть подтянуты резисторами к питанию. Впрочем, если используется полноценный Push-Pull то подтяжка не нужна — выход сам поднимет ногу на нужный уровень.

Работает следующим образом.
Матричная клавиатура
Матричная клавиатура
Расширение разрядности дешифратором
Расширение разрядности дешифратором
Используя счетчик
Используя счетчик

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

Теперь считываем сразу все значение из читающего порта. Если на столбце А не нажата ни одна кнопка, то в порту будут все единички. Но стоит нажать любую кнопку из столбца А, так она сразу же замкнет линию А, на этот вывод порта. В линии А у нас в данный момент 0, это обеспечивает ноль на сканирующем выводе контроллера. Поэтому и на соответствующем выводе порта будет 0
Так что, если будет нажата кнопка, например, 6, то на линии Р1 будет 0.

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

Можно определить одновременные нажатия многих кнопок — надо просто делать проверку не по байту, а по конкретному биту.

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

Дешифратор, это такая микросхема, принимающая на вход двоичный код, а на выходе выдает единицу в выбранный разряд. Т.е. подали число «101″ — получили «1″ на выводе номер 5. Ну, а у инверсного дешифратора будет 0.

Можно пойти еще дальше и поставить микросхему счетчик, который дергать импульсом с порта, значение со счетчика прогонять через дешифратор. Таким образом, можно влепить сколько угодно выводов, хватило бы разрядности дешифратора. Главное учитывать на каком такте счетчика у нас будет какой столбец.

Если сканируется обычная клавиатура, нажимаемая человеком, то можно не заморачиваться на скорость опроса и сделать его в качестве побочного продукта, повесив на какое-нибудь левое прерывание. Достаточно чтобы клава опрашивалась хотя бы 10-20 раз в секунду. Этого уже достаточно, для комфортной работы.

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

Но микроконтроллер работает с такой скоростью, что успевает посчитать эти всплески как устойчивые состояния. Решить эту проблему можно аппаратно, с помощью RS триггера, так и программно — внеся небольшую задержку перед следующим опросом кнопки. Задержка подбирается такой, чтобы дребезг успел прекратиться к ее окончанию.

Запись опубликована в рубрике Начинающим с метками , , , , . Добавьте в закладки постоянную ссылку.

68 комментариев: Матричная клавиатура

  1. foxweb говорит:

    Интересная тема. Про матрицу знаю. Про дешифратор тоже догадывался. А про счётчик — что-то новое. Ещё можно заметить, что таким же образом можно не только вводить данные, но и выводить их, например на светодиодную матрицу. Да?

    • DI HALT говорит:

      В принципе можно. Тоже подключаешь нужный столбец к земле ножкой проца, а на строку даешь напругу. Только тут надо будет убрать подтяжки и оба выхода сделать на Push-Pull.

      • nwanomaly говорит:

        а если надо нажать одновременно несколько кнопок в одном ряду или вывести в этот ряд несколько светодиодов из матрицы?

        • foxweb говорит:

          А вы ещё не поняли, что матрица быстро-быстро сканируется по строка м столбцам, как двумерный массив?

          «Потом число в сканирующем порту сдвигается на один бит влево (или вправо) и сканируется второй столбец и так по кругу. В итоге, зная какой столбец мы сканируем, получив ноль на считывающем порту, мы, как по координатам, поймем какая кнопка из матрицы нажата.»

          • Mazayac говорит:

            При такой схеме будут проблемы с одновременным распознаванием при нажатии некоторых групп кнопок. Для точного определения нужно водить в схему диоды.

          • DI HALT говорит:

            Ввел :)

          • Stebanoid говорит:

            Для тех, кто не сразу врубился, какие могут быть проблемы — при нажатии двух кнопок в одной строке, два сканирующих порта оказываются замкнутыми накоротко, причём один из портов ставит 0, а второй 1. Будет нехорошо.

          • DI HALT говорит:

            Если диоды стоят, то ничо страшного не произойдет.

          • Stebanoid говорит:

            Ну так я собственно и объясняю для тех, кто не понял, зачем эти диоды нужны. :)

          • gleb говорит:

            а если вместо диодов программно переключать порты на вход (кроме сканирующего в данный момент)?

          • DI HALT говорит:

            Здравая мысль. А подтяжку сделает внутренний резистор. Можно и так.

          • demiurg1978 говорит:

            Не надо никаких диодов. Я делал по такой схеме. 4×4 клава. В тот раз это был один порт. Но это не критично. На все 8 выводов порта вешаем подтягивающие резисторы. Порты в высокоомном состоянии. Даже не нужно внутренние резисторы подтягивать. Мы их уже припаяли. Алгоритм примерно следующий:

            => там кусок кода http://easyelectronics.ru/repository.php?act=view&id=25

            Сколь бы кнопок не нажали одновременно, они все будут в переменной KEY_SCAN. Не трудно даже в AVR-Studio прогнать, проверить.

          • Mazayac говорит:

            Ну так об этом два года назад тоже написано было :)
            «Mazayac 08 Сен 2008 13:33
            С такой простейшей схемой надо выводить в сканирующий порт не “значение, состоящее из одного нуля и единицы на всех остальных выводах”, а “все выводы сканирующего порта переключаем на вход (обеспечивая Z-состояние), далее один из выводов порта переключаем на выход, и выдаем на него ноль”.»

        • DI HALT говорит:

          Совсем прям одновременно нельзя. Но можно же это сделать по очереди. Если делать все быстро-быстро никто и не заметит подставы :)

  2. Mazayac говорит:

    Без диодов на сканирующем порту получим КЗ при замыкании двух кнопок в разных столбцах!

    • DI HALT говорит:

      Угу, добавил. Совсем забыл про эту проблему. Т.к. всегда делал клаву только на АТ89С51 а у него квазидвунаправленные порты, поэтому там КЗ в принципе сделать низя.

  3. Mazayac говорит:

    С такой простейшей схемой надо выводить в сканирующий порт не «значение, состоящее из одного нуля и единицы на всех остальных выводах», а «все выводы сканирующего порта переключаем на вход (обеспечивая Z-состояние), далее один из выводов порта переключаем на выход, и выдаем на него ноль».

  4. Fi5t говорит:

    Сухая теория =) Хоть бы кодом разбавил. Щас буду кстати делать эту самую клавиатуру… мать ийо так =)

  5. Mazayac говорит:

    Для использования счетчика надо задействовать его вход Reset, т.к. многие счетчики не гарантируют «нулевого» состояния при подаче питания.

  6. Susanin говорит:

    Здравствуйте. Начал почтигать AVR с вашего сайта. Большое спасибо за различного рода инфу. Я даж на рабостях микроконтроллер приобрёл AT89C52 , бегущие огоньки хотел сделать.

  7. 'R Dee говорит:

    На первой схеме, с клавиатурой, кнопки странно пронумерованы.
    Их всего вроде 25, а не 26.

    Спасибо за статью.

    Интересно еще было бы почитать про то, как правильно использовать RS триггер. У меня почему то не получилось и дребезг дальше проникает за триггер.

    • Stebanoid говорит:

      А как именно ты триггер использовал?

      • 'R Dee говорит:

        Мне нужно было сделать что бы можно было четко фиксировать состояние (включено/выключено). Сделал по типовой схеме найденой в интернете. В результате, малейшее случайное касание проводников меняло состояние триггера. Нажатие кнопки приводило к множественному изменению состояний и в результате неизвестно было, где он остановится.
        Понимаю, что надо дополнительную обвеску делать, что бы избавится от этого влияния, но как именно — тут уже не хватает знаний.

  8. berrymorr говорит:

    berrymorr. kicks-ass. org /avrkbd.png
    а так можно организовать клавиатуру (если не бояться нажатия нескольких кнопок)?

    ldi r16,0xF0
    out DDRA,r16
    ldi r16,0x0F
    out PORTA,r16
    • DI HALT говорит:

      Без диодов нежелательно. А так можно. Какие проблемы? Разве что тебе придется заморочиться на сдвиг полупорта, но это не велика проблема — битовые маски тебе в помощь.

      • berrymorr говорит:

        просто что у вас, что в атмеловских аппноутах подтяжка есть.
        а куда тогда диоды втыкать, если без подтяжки?

        • DI HALT говорит:

          А ты хочешь забить на возможный КЗ и сделать без резисторов. В таком случае подтяг не нужен — ты уровень жестко задаешь столбцом. Но нажал две разные кнопки и спалил порт. Оно тебе надо?

          • berrymorr говорит:

            так вроде же диоды от КЗ спасали?
            от КЗ защищена схема только с диодами и подтягом?
            если нет, то какой может быть простейшая схема с защитой от КЗ?

          • DI HALT говорит:

            Они спасут от КЗ, но они же не дадут ногу поднять вверх. Поэтому и нужен внешний подтяг.

          • DI HALT говорит:

            Хотя не. Подтяжку дает регистр считывающего порта. Слабую но дает. Уровень задает столбец. Низкий уровень нам прокачает, а высокий нам не важен. Один фиг на низкий работает. Да, будет работать без подтяжки и с диодами.

  9. testicq говорит:

    Видел другой вариант клавы — цепочка резисторов одинакового номинала от VCC до GND, а все места соединения резисторов через кнопки подключены ко входу АЦП. собственно т.к. все резисторы одинакового номинала, то при нажатии на кнопку получаем на входе ацп напряжение VCC/число резисторов*порядковый номер кнопки, ну а на выходе ацп — уже сразу готовый байт. только в младших разрядах думаю будет мусор — поэтому можно сдвинуть байт вправо. ну и подобрат разницу напряжений на кнопках, чтобы лучше ложилась в разрядную сетку ацп.

  10. denilson говорит:

    1. DI HALT, а как, если не нажата клавиша, в считывающем порту будут единицы? На рисунке выводы этого порта как в воздухе висят, откуда на них идет плюс?

    2. А зачем диоды в схеме?

    • DI HALT говорит:

      Подтягивающие резисторы внутри МК. Можно внешние резисторы поставить, не помешает.

      А чтобы при нажатии кнопок на одной строке не было кз между столбцами. На них ведь 0 и 1 будут.

      • denilson говорит:

        Все равно не понял, так это же вроде входа у нас, как на них 1 тогда появилась? Мы не с Vcc берем?

        • DI HALT говорит:

          Покури матчасть, а именно работу портов МК.

          У АВР или ПИК (а у классического С51 только так и могут) порты могут работать на вход с подтяжкой. Т.е. он изнутри всегда на Vcc подцеплен через резистор и когда сигнала нет дает 1, а извне мы можем приложить его к земле.

          Да, речь идет о защите от замыкании между собой ножек А В С Д на сканирующем порту.

  11. kaktus37 говорит:

    извиняюсь конечно если фигню сморожу, но разве неможно принимающий порт выставить в высоко импедансное состояние и тупо слушать. тогда можно как на ВВ59 4 бита на строку и 4 на столб, имеем 16 кнопочков… или я чот недопонял очень?

    • DI HALT говорит:

      А как ты отличишь на какой строке/столбце было нажатие? Только сканом!

      • kaktus37 говорит:

        эм… ну допустим… эм… блин, да. но зато можно не париться над козами и подтягами =)

        • DI HALT говорит:

          Ещеб оно работало при этом. Хы. Можешь сам попробовать :)

        • kaktus37 говорит:

          или опять глубокое заблуждение?

          • DI HALT говорит:

            Попробуй! Никто от этого не умрет, зато поймешь в чем ты заблуждаешься :)

          • kaktus37 говорит:

            в принципе это и есть самый прямой способ научиться и понять :)

          • kaktus37 говорит:

            в теории правда выглядит всё красиво… как я понял из комикса с упячко-мэном :) то скан можно делать внутренний (не знаю как правильно) и при этом имея нажатия допустим на 2х кнопках, получим что-то вида 1101 1001 ( нажаты будут клавиши 3го столбца 2ой и 3её строки) вот как-то так.

          • DI HALT говорит:

            Вот только если у тебя и строка и столбец будут в hiz то откуда у тебя будут уровни то?

  12. 486DX говорит:

    А есть возможност подключить нормальную клавиатуру PC/XT/AT?
    Или только эту 25 (ксатити, там либо ошибка: 24клавиши нет) клавишную?
    просто если нельзя, то придется весть функцилнал снова дорабатывать.

    • DI HALT говорит:

      Можно, даже проще чем тут. У писишной клавы есть свой контроллер который в последовательном формате (похожем на SPI) выдает информацию. Остается только ее декодировать.

      • 486DX говорит:

        значит, надо искать таблицу соответствий сигналов с клавы и символов? А подключать как? для каждого типа клавы (PC/XT или PS2) разные как и сигналы, так и выводы.

        • DI HALT говорит:

          Ищи описание интерфейса PS/2 там все по идее расписано.

          • 486DX говорит:

            таблицу нашел, разобрался. Теперь подключение:
            data — данные (на uart вешать?)
            n/c — тут понятно
            земля — понятно.
            +5В — тоже, вроде, без проблем
            Clock — это типа синхронизация, то есть подаёшь на data бит информации и дёргаешь за неё и бит записан.
            Правильно? Куда clock девать? Отдельную линию подтверждения передачи данных (если я с ума не сошёл)?

          • DI HALT говорит:

            Ша, разбежался. Не так все просто. UART тут вообще не причем.

            Точно протокол не помню. Там вроде как данные доступны для чтения на высоком уровне сигнала Clock.

            Т.е. дрыгаешь клоком, и снимаешь данные с data.

  13. 486DX говорит:

    Ещё вопрос есть: какие параметры у используемых диодов?

  14. crab говорит:

    А можно по идее аналогичным образом скоммутировать матрицу, скажем, из пьезодатчиков/микрофонов на АЦП?(не спрашивайте зачем).

  15. Vitasok говорит:

    Есть вопрос по схеме «Матричная клавиатура». Просвятите новичка ).
    Пины на строках находятся в состоянии «Вход Hi-Z» в внешней или внутренней подтяжкой. Это понятно. А вот со столбцами есть вопрос. Если при неактивном столбце на нем «жесткие» +5, то зачем нужны подтягивающие резисторы в столбцах. Если там +5 от подтяжки, а пин в Hi-Z, то зачем диоды?

  16. able говорит:

    Di Halt, я в Proteus’e нарисовал схемку с матрицей клавиатуры, как у тебя на картинке.
    В сканирующий порт посылаю байтик с нулём, а при нажатии кнопки подтяжка из читающего порта передавливает ноль и в сканирующем порту на месте ноля оказывается единица, в читающем порту ничего не меняется, т.е., как были все единички от подтяжки, так и остаются.
    Это глюк Proteus’a, или я что-то не так понял?

  17. DX168B говорит:

    Я обычно применяю дешифраторы. Например, совковый К155ИД3.
    Плюсы — всего 5 ног МК на опрос 16-ти кнопок.
    Ну и простота п\программы опроса кнопок.
    Мы подаём значение в порт МК, проверяем, нет ли нажатия. Далее, если нажатия нет, то инкрементируем регистр и снова подаём в порт. Если зафиксировано нажатие, то тупо спрыгиваем с цикла, а в регистре у нас остаётся номер нажатой кнопки.

    Ну а минусы — Габаритность, чуть большая стоимость и чуть большее энергопотребление.
    То есть, метод не совсем годится для критичных к этим параметрам устройств.

  18. SOF говорит:

    Допустим, что у нас сейчас ноль на в первом столбце, а нажата первая клавиша из второго столбца. Ток опять может пойти от единицы порта P0 через резистор R2 на ноль столбца А. Получаем ложное детектирование нажатия клавиши, или нет?

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