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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

82 thoughts on “Матричная клавиатура”

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      1. Да понятно, но даже для обобщенного счетчика можно дать понять, что 1 выводом микроконтроллера не обойтись :)

        1. Почему? А кто мешает сбросить счетчик RC цепью? А циклический пересчет делать по последнему разряду или по переполнению?

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

    1. С АТ89С52 ты погорячился. К нему спец программатор нужен. И вообще это не AVR а MSC-51 — совершенно другая система команд и архитектура.

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

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

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

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

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

    ldi r16,0xF0
    out DDRA,r16
    ldi r16,0x0F
    out PORTA,r16
    1. Без диодов нежелательно. А так можно. Какие проблемы? Разве что тебе придется заморочиться на сдвиг полупорта, но это не велика проблема — битовые маски тебе в помощь.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    1. Всё, нашёл )
      Надо было не использовать готовый keypad, а нарисовать матрицу самому из отдельных кнопок.

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

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

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

  16. Если нажать кнопки 6,7,2, то ваша схема будет считать, что нажата и кнопка 1. Чтобы этого избежать, нужно на каждую кнопку ставить диод.

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

  17. Добрый день, DI. Планируется контроллер освещения. Управление из нескольких мест. Подключение кнопок витой парой. Максимальное расстояние — метров 25. Возникает вопрос. Будет ли эта паутина ловить наводки и если будет, то как с этим бороться?

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

    1. И вопрос по поводу дребезга, можно ли его устранить с помощью конденсатора малой емкости или же это неправильное решение?

      1. Можно, но всех проблем это не решает. А еще вызывает лишнее искрение на кнопке. Лучше решать проблему программно.

        1. Обычно программно и делал, потом прочитал книгу Платта, он там как раз решает конденсатором искрение, начал думать, что это я физический вопрос пытаюсь решить программно. Получается, где у нас есть мозги можно сэкономить деньги и батарейку и решить проблему кодом.

      1. есть такие 1N4148 и 1N4728A, можно заюзать, маломощный это сколько, в основном все по 1 ватту или надо еще более слабые? На схеме диоды проставлены в каждом столбце, разве они должны быть не возле каждого переключателя? Спрашиваю в контексте компьютерной клавиатуры, сейчас пробую собрать, надо чтобы каждая клавиша определялась отдельно (NKRO, n key rollover по английски).

        1. 1ВТ это дофига. Реально хватит и 0.25 и даже меньше. Диоды тут стоят для защиты от КЗ при нажатии двух кнопок на сканцикле. Можно и без них, но сканировать надо не в 10111 маске, а в Z0ZZZ. Не у всех МК вывод может быть в Z состоянии.

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

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

Перед отправкой формы:
Human test by Not Captcha