Схема матричной клавиатуры. AVR. Учебный курс. Процедура сканирования клавиатуры. Задание к работе в лаборатории

При необходимости использования в устройстве клавиатуры с большим количеством кнопок, например в кодовом замке, очень часто применяют матричную клавиатуру. Если подключить 12 кнопок обычным способом потребуется 12 выводов микроконтроллера плюс общий провод, в матрице же используется всего один порт контроллера, что способствует экономии выводов контроллера. Кнопки в такой клавиатуре подключаются к общим столбцам и к общим строкам, линии порта микроконтроллера разделяются на ввод PB7-PB4 и вывод PB3-PB0. В каждый момент времени сигнал низкого уровня (логический ноль) подается только на одну строку кнопок, на остальные должна подаваться логическая единица. Это исключит неоднозначность определения номера нажатой кнопки. Двоичные сигналы, присутствующие при этом на столбцах клавиатуры, считываются через порт ввода микроконтроллера.

В программе обязательно организовываем бесконечный цикл. В специальной функции производим опрос клавиатуры, анализируем полученные данные и выводим результата на индикатор. Опрос клавиатуры заключается в последовательном сканировании каждой строки, для этого на соответствующую линию порта вывода подается логический ноль (эквивалент общего провода), на остальных строках должен быть высокий уровень, после чего с порта ввода, к которому подключены столбцы, считывается код. Если считаны все единицы, то ни одна из клавиш не нажата, в противном случае код содержит информацию о нажатых клавишах. Стоит заметить, что считанный код содержит не только номер замкнутого контакта, но и информацию о нажатии нескольких кнопок одновременно, поэтому лучше хранить в памяти контроллера непосредственно считанный код, а не готовый номер кнопки. Для хранения считанного кода следует ввести специальный алгоритм и переменные.

Ниже показан пример программы в которой при нажатии определенной клавиши ее значение высвечивается на семисегментном индикаторе. Микроконтроллер Atmega8 работает от внутреннего генератора частотой 8MHz.

/*** Подключение матричной клавиатуры к микроконтроллерам AVR ***/ #include #include // Массив значений для порта вывода unsigned char key_tab = {0b11111110, 0b11111101, 0b11111011, 0b11110111}; // Функция опроса клавиатуры unsigned char scan_key(void) { unsigned char key_value = 0; unsigned char i; for(i = 0;i < 4;i++) { PORTB = key_tab[i]; // выводим лог. 0 в порт вывода _delay_us(10); switch (PINB & 0xF0) { case 0b11100000: key_value = 1 + i * 3; return (key_value); case 0b11010000: key_value = 2 + i * 3; return (key_value); case 0b10110000: key_value = 3 + i * 3; return (key_value); default: break; } } return (key_value); } int main(void) { // массив цифр для индикатора unsigned char num = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F}; DDRB |= (1 << PB3)|(1 << PB2)|(1 << PB1)|(1 << PB0); // Порт вывода DDRB &= ~(1 << PB7)|(1 << PB6)|(1 << PB5)|(1 << PB4); // Порт ввода PORTB = 0xF0; // Устанавливаем лог. 1 в порт ввода DDRD = 0xFF; // Выход на индикатор PORTD = 0x00; _delay_ms(10); while(1) { // Выводим значение нажатой кнопки на индикатор if(scan_key()==1) PORTD = num; if(scan_key()==2) PORTD = num; if(scan_key()==3) PORTD = num; if(scan_key()==4) PORTD = num; if(scan_key()==5) PORTD = num; if(scan_key()==6) PORTD = num; if(scan_key()==7) PORTD = num; if(scan_key()==8) PORTD = num; if(scan_key()==9) PORTD = num; if(scan_key()==11) PORTD = num; } }

Архив для статьи "Подключение матричной клавиатуры к микроконтроллерам AVR"
Описание: Проект AVRStudio и Proteus
Размер файла: 37.33 KB Количество загрузок: 1 905

В этой статье мне бы хотелось познакомить читателей с подключением к микроконтроллерам клавиатуры. Дело в том, что обычно большинству схем на микроконтроллерах для ввода данных требуется одна или несколько кнопок. Но, когда проекты становятся сложнее, может возникнуть потребность в применении небольшой клавиатуры. Встречаются варианты клавиатур 3х4 или 4х4, и почти всегда клавиши в них соединены по схеме матрицы. Применение матрицы необходимо из -за того, что для её подключения нужно минимальное число линий ввода - вывода. Например, для клавиатуры 4х4 необходимо, состоящей из 16 кнопок необходимо 16 линий ввода, поэтому рациональнее организовать её в виде матрицы, т.е. расположить 4 кнопки в 4 строки, использовав 8 линий ввода - вывода (один порт микроконтроллера). Самое распространённое решение подключения матрицы на один порт - это подключить строки к старшим разрядам, а столбцы к младшим. Однако, здесь возникает проблема - считывание состояния клавиатуры происходит при возникновении прерывания, но в микроконтроллере ATtiny2313 мы можем использовать два внешних прерывания (остальные выводы заняты). Эта проблема решается подключением четырёх диодов, образующих с подтягивающим резистором на входе INT0 элемент «ИЛИ».

Схема подключения клавиатуры 4х4 матричного типа к микроконтроллеру приведена на Рис.1. Она имеет разъём DB-9F, преобразователь уровней MAX3232, которые необходимы для взаимодействия UART микроконтроллера с RS-232, и работа которых была описана в предыдущей статье. Резисторы R3 - R6 защищают микроконтроллер от короткого замыкания питания на землю. На входе INT0 имеется подтягивающий резистор R7 . Четыре диода VD1 - VD4 подключены к линиям ввода- вывода клавиатуры (катодами) и к выводу INT0 (анодами). Теперь при нажатии любой кнопки, если на столбцы подать нули, на входе INT0 появится низкий уровень.

Как показано на Рис.1 клавиатура подключена к порту В микроконтроллера. Её схема представлена на Рис.2.

Предположим, что весь порт В настроен на вход, и все входа имеют подтяжку:

DDRB = &B00000000

PORTB = &B11111111

Пусть кнопки (Рис.2) каким -то образом соединены ещё и «землёй» (GND), тогда при нажатии, например, кнопки «1» на контактах порта В РВ3 и РВ4 будет низкий уровень, т.е. порт примет значение PORTB = &B11100111, которое и является кодом кнопки «1». Аналогично и в отношении остальных кнопок (код кнопки «В» - 01111011, «5» - 11011011 и т.д.). Но, поскольку кнопки не соединены с GND, необходимо ввести раздельное определение строк и столбцов с последующим суммированием и идентификацией результата с названием кнопки.

Сделаем строки РВ0 - РВ3 входами и включим их подтяжку, а столбцы РВ3 - РВ7 - выходами:

DDRB = &B11110000

PORTB = &B00001111

При нажатии кнопки определённая строка будет иметь низкий уровень. Например, при нажатии кнопки «1» порт В примет значение 00000111, которое является кодом строки. Одновременно с этим включится прерывание, при обработке которого необходимо считать данный код в переменную Stro:

Инвертируем настройки порта - сделаем столбцы РВ3 - РВ7 входами и включим их подтяжку, а строки РВ0 - РВ3 - выходами:

DDRB = &B00001111

PORTB = &B11110000

Теперь при нажатой кнопке «1» порт будет иметь значение 11100000, которое является кодом столбца. Считаем этот код в переменную Col.

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

Чаще всего встречаются клавиатуры 3х4 и 4х4 с 12-ю и 16-ю кнопками, соответственно. У меня в руках оказалась клавиатура 4х4. Работу с ней сейчас и рассмотрим.

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

Потыкав по кнопкам, с помощью мультиметра установил как соединены кнопки внутри клавиатуры.


Для сканирования матричных клавиатур в Bascom-AVR существует специальная функция Getkbd () . Эта команда заточена под использование клавиатур 4х4, поэтому она использует все 8 выводов одного порта микроконтроллера. И в случае использования клавиатур c меньшим числом кнопок стоит это учитывать.

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

к примеру, в следующей строке:

Config Kbd = Portd , Debounce = 20 , Delay = 100

сконфигурировано подключение клавиатуры к PortD, время дребезга установлено 20 мс, время задержки после нажатия 100 мс

Эта команда берет на себя всю работу по сканированию строк клавиатуры и возвращает переменной номер нажатой клавиши от 0 до 15. Если нажатия на кнопку не зафиксировано, тогда функция вернет число 16. Дальше, в зависимости от того как соединены кнопки, может потребоваться узнать символ нажатой кнопки.

В приведенном ниже примере, сканирование клавиатуры происходит с частотой 10 Гц и находится в главном цикле программы. Результат нажатий выводится на ЖК дисплей.

$regfile = "m8def.dat"
$crystal = 1000000

"конфигурация дисплея
Config Lcdpin = Pin , Rs = Portc . 0 , E = Portc . 1 , Db4 = Portc . 2 , Db5 = Portc . 3 , Db6 = Portc . 4 , Db7 = Portc . 5
Config Lcd = 20 * 4
Cursor Off
Cls

"конфигурация клавиатуры
Config Kbd = Portd , Debounce = 20 , Delay = 100


"переменные
Dim Key_char As Byte "номер нажатой клавиши
Dim Key_str As String * 1 "символ нажатой клавиши на клавиатуре
Dim Result As String * 20 "результат нажатий на клавиатуру

Result = ""

"Главный цикл программы
Do

Key_char = Getkbd () "клавиша не нажата и функция возвращает переменной значение 16

If Key_char <> 16 Then "если переменная не равна 16, значит была нажата кнопка
Key_str = Lookupstr (key_char , Keyboard_data ) "вытаскиваем символ нажатой клавиши
Result = Result + Key_str
End If

Locate 1 , 1

Lcd Result "выводим на дисплей результат нажатий

Waitms 100

Loop

End

Keyboard_data :
Data "1" , "4" , "7" , "*" , "2" , "5" , "8" , "0"
Data "3" , "6" , "9" , "#" , "A" , "B" , "C" , "D"

А вот тестовая схемка, по которой подключаются дисплей и клавиатура:

Еще в схему не мешало бы добавить токоограничительные резисторы на линию клавиатуры, номиналом 100-150 Ом. На всякий случай, но для пробы сойдет и так (главное не нажимать сразу несколько кнопок)

Подключаем, прошиваем, тыкаем на кнопки и видим результат - на дисплей выводятся символы нажатых клавиш:


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

А пока можно скачать архив в котором находится файл для симуляции в Proteus и прошивка.

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

Большая часть текста содержит объяснение программного кода, его можно скачать либо посмотреть видео под статьей.

Сделать такую клавиатуру можно и самому. Для этого понадобится печатная плата, 12 или 16 обычных кнопок и соединительные провода. Я же буду использовать готовую.

Для чего нужна матричная клавиатура?

Для примера возьмем обычную кнопку. Как вы знаете, это простейшее электромеханическое устройство. Чтобы подключить ее к плате, нужно использовать стягивающий резистор, а также задействовать по одному контакту питания и «земли». Нажатием такой кнопки можно выполнить определенное действие, например можно управлять светодиодом, различными приводами, механизмами и так далее. А что, если нам необходимо подключить несколько кнопок? Тогда придется задействовать больше контактов и большее число проводов, да и без макетной платы уже не обойтись, плюс еще резисторы придется использовать в большем количестве.

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

Подключать ее к плате следует 8 выводами, каждый из них считывает значения с определенных строк и столбцов. Подключать их следует к выводам на панели Digital. Я подключу, например, к выводам от 2 до 9 включительно. Нулевой и первый трогать не желательно, поскольку они предназначены для UART интерфейса (например, для подключения блютуз-модуля). Рациональнее оставить их свободными.

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

После того, как вы установили в библиотеку, можно зайти в Ардуино IDE (программа с сайта Arduino) и посмотреть примеры скетчей.

Возьмем самый простой скетч для ознакомления. Он позволяет считывать значение с клавиатуры при нажатии определенной клавиши и выводить их в порт. В данном случае это монитор порта на компьютере.

#include // подключаем нашу библиотеку




{"2","5","8","0"},
{"3","6","9","#"},
{"A","B","C","D"}
};




void setup(){
Serial.begin(9600);
}
void loop(){

if (customKey){
Serial.println(customKey);
}
}

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

Если это сделать неправильно, то, например, при нажатии цифры 4, в порт выйдет цифра 6 или любой другой символ. Это можно определить опытным путем и расположить символы, как они расположены на клавиатуре.

В функции void setup указываем скорость последовательного соединения с монитором порта 9600 бод . Функция нужна только для подачи питания на модули. В функции Void Loop прописываем условие. Переменная Char используется для хранения только одного символа, например, 1, А или 5, что подходит к ситуации. Если нажатие зафиксировано, то происходит вывод символа в монитор порта с помощью функции Serial Print. В скобках нужно указывать, какую переменную выводим в порт. Если все сделано верно, в мониторе порта получим символ, на который нажимали. Не забудьте в мониторе порта внизу справа указать скорость передачи данных такую же, как в скетче.

Схема с дисплеем и матричной клавиатурой

Давайте выведем данные на дисплей.

Я использую дисплей, сопряженный с модулем I2C, который упрощает подключение. Для работы с дисплеем с шиной I2C необходимо установить еще одну библиотеку. Скачать ее можно .

Далее нужно указать размерность дисплея. Используемый в примере дисплей вмещает по 16 символов в каждой из 2-ух строк, это я и указываю. В функции Void Setup нужно подать питание на дисплей и включить подсветку. Делается это с помощью двух функций: lcd.begin и lcd.backlight .

#include // подключаем нашу библиотеку
#include
LiquidCrystal_I2C lcd(0x27, 16, 2);
const byte ROWS = 4; //число строк у нашей клавиатуры
const byte COLS = 4; //число столбцов у нашей клавиатуры
char hexaKeys = {
{"S","4","7","*"}, // здесь мы располагаем названия наших клавиш, как на клавиатуре,для удобства пользования
{"O","5","8","0"},
{"S","6","9","#"},
{"I","B","C","D"}
};
byte rowPins = {5, 4, 3, 2}; //к каким выводам подключаем управление строками
byte colPins = {9, 8, 7, 6}; //к каким выводам подключаем управление столбцами
//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
void setup(){
Serial.begin(9600);
lcd.begin(); // Инициализируем экран
lcd.backlight();
}
void loop(){
char customKey = customKeypad.getKey();
if (customKey){
Serial.println(customKey);
lcd.setCursor(1,4); //устанавливаем курсор
lcd.print(customKey);
}
}

В функции Voil Loop нужно в самом условии прописать строчку lcd.print для вывода данных на дисплей. И еще нужно предварительно установить положение курсора. В скобках идут 2 цифры: первая — это номер символа, а вторая — номер строки. Нужно помнить, что у этого дисплея отсчет строк и столбцов начинается не с единицы, а с нуля. То есть здесь имеются строчки под номерами 0 и 1, а не 1 и 2, как может показаться сначала. Затем загрузим код в плату и посмотрим, что будет.

Так как дисплей работает по интерфейсу I2C, подключаем к аналоговым выводам. Выходы SDA и SCL соответственно подключаем к А4 и А5, а остальные два — это уже питание и «земля».

Как видим, нажимая на любой символ, видим его отображение на дисплее.

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

Подключение клавиатуры к Arduino и управляющее действие

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

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

Подключение светодиода

Я буду использовать макетную плату и резистор (желательно использовать от 150 до 220 Ом). Двумя перемычками замкну схему, подключив их к пинам питания и земли на плате Ардуино.

Схема будет работать так: при нажатии на 1 включается светодиод, при нажатии на 2 — выключается.

Светодиод в примере подключен к пину 8 на плате Ардуино.

#include
const byte ROWS = 4; // Four rows
const byte COLS = 4; // Three columns
char keys = { // Define the Keymap
{"1","4","7","*"}, // здесь мы располагаем названия наших клавиш, как на клавиатуре,для удобства пользования
{"2","5","8","0"},
{"3","6","9","#"},
{"A","B","C","D"}
};
byte rowPins = { 5, 4, 3, 2 };// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte colPins = { 9, 8, 7 ,6}; // Connect keypad COL0, COL1 and COL2 to these Arduino pins.
Keypad kpd = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);// Create the Keypad
#define ledpin 8
void setup()
{
pinMode(ledpin,OUTPUT);
Serial.begin(9600);
}
void loop()
{
char key = kpd.getKey();
if(key) // Check for a valid key.
{
switch (key)
{
case "1":
digitalWrite(ledpin, HIGH);
break;
case "2":
digitalWrite(ledpin, LOW);
break;
}
}
}

Давайте разберем скетч.

Возьмем первый скетч урока и просто его дополним. В начале с помощью полезной функции Define присвоим название подключенному к пину 8 светодиоду ledpin . В функции Void setup указываем сигнал со светодиода как выход.

Если бы не библиотека Кейпад для клавиатуры, пришлось бы прописывать то же самое для 8 пинов, с которыми связана клавиатура. В функции void loop условие. Нажатие определенной клавиши «приравнивается» к значению переменной key. Оператор Switch сравнивает значения переменной key и «дает» определенные команды в зависимости от этого значения. Состоит он из двух вспомогательных операторов Case и Break . Проще говоря, если будет найдено значение переменной, равное 1 , то будет выполняться действие. Оператор break служит командой выхода из оператора Case .

Соответственно при нажатии на 1 будет выполняться максимальная подача напряжения на светодиод и он будет гореть. При нажатии на 2 он гореть не будет. Это указывается в функции Digitat write , где в скобках задается название переменной и «указание» ей. Можно таким образом написать определенные команды для каждой кнопки и управлять большим количеством светодиодов или создать команду для включения всех светодиодов сразу.

Отличительные особенности:

  • 64- кнопочная клавиатура в виде матрицы 8 х 8
  • Не требуется внешних компонентов
  • Выход из режима "сна" по нажатию на кнопку
  • Легкая интеграция с другими приложениями
  • Низкое потребление
  • Программный алгоритм антидребезга
  • Поддержка альтернативных функций кнопок, которая для сокращения размера программы может быть легко удалена
  • Код программы может использоваться любым AVR микроконтроллером, имеющим не менее 17 линий портов ввода - вывода и имеющим прерывание по изменению состояния линий (в настоящее время это только ATmega162 и ATmega169)
  • Код может быть легко модифицирован для применения в других микроконтроллерах, использующих общее прерывание (см. пример применения "AVR240: 4 x 4 Keypad - Wake-up on Keypress")

Введение

В данном примере применения описывается программа драйвера интерфейса клавиатурной матрицы 8 x 8. Пример применения разработан для использования в устройствах с автономным питанием. AVR микроконтроллер большую часть времени проводит в режиме сна, активизируясь лишь тогда, когда происходит нажатие кнопок клавиатуры. После этого происходит сканирование клавиатурной матрицы, обработка информации и возврат в режим пониженного потребления.

Также устройство, описываемое в данном примере применения, поддерживает альтернативные программируемые пользователем функции типа Caps Lock, Ctrl-, Shift- и Alt-. Тестовое приложение обслуживает клавиатурную матрицу 4 x 4, каждой кнопке которой соответствует одна цифра и три символа. Альтернативные кнопки позволяют выбрать функцию нажимаемой кнопки.

Рисунок 1. Тестовое приложение

Это устройство подходит для всех приложений, использующих матричную клавиатуру, например, пульты дистанционного управления, мобильные телефоны и системы аварийной сигнализации и контроля доступа. Обновление программного обеспечения производится очень легко за счет наличия у микроконтроллеров семейства ATmega функций самопрограммирования и внутрисистемного программирования. Эти функции особенно полезны при использовании этих микроконтроллеров в универсальных пультах дистанционного управления.

Устройство, описываемое в данном примере применения, построено на микроконтроллере ATmega162. Однако, после небольших изменений код программы может использоваться в микроконтроллере ATmega169.

Принцип действия

Подключение кнопок клавиатурной матрицы 8 x 8 показано на рисунке 2. При нажатии на кнопку происходит соединение соответствующих строк и столбцов. При нажатии на левую верхнюю кнопку происходит замыкание самого левого столбца и самой верхней строки.


Рисунок 2. Подключение клавиатурной матрицы

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

Если необходимо обслуживать клавиатуру, допускающую одновременное нажатие кнопок, то описанный выше метод не может быть использован. В этом случае строки должны быть отсканированы отдельно. Строки должны быть выбраны (устанавливается низкое значение) последовательно, при этом снимается состояние всех столбцов. При этом определяются все нажатые кнопки. Однако в этом случае появляются межсоединения. На рисунке 3 показан результат нажатия трех клавиш, при котором кажется, что нажата еще и кнопка, помеченная иксом. Это приводит к появлению ошибки декодирования.


Рисунок 3. Ложное декодирование при одновременном нажатии кнопок

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

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

Альтернативные кнопки

Многие клавиатурные интерфейсы используют функции вспомогательных кнопок. Реализовано это может быть несколькими способами. Один из самых распространенных методов состоит в выделении нескольких кнопок, которым назначаются альтернативные функции. При одновременном нажатии этих и обычных кнопок формируется вторичной скан-код. Также существуют варианты, когда альтернативная кнопка нажимается непосредственно перед нажатием основной кнопки. В этом случае устраняется необходимость отслеживания одновременных нажатий.

Альтернативные кнопки принимаются во внимание только в том случае, когда нажаты основные кнопки. В этом случае альтернативные кнопки называются "одновибраторными".

Также возможно реализовать "триггерные" кнопки, которые при первом нажатие активизируют альтернативные функции, а при повторном нажатии отключают их. В этом случае используются альтернативные функции для всех нажимаемых впоследствии кнопок. Такие функции имеет кнопка Caps Lock на стандартной компьютерной клавиатуре. В данном примере применения используется как одновибраторные, так и триггерные кнопки.

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

Дребезг контактов

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


Рисунок 4. Дребезг контактов

Реализация

В данной реализации использован микроконтроллер ATmega162. Рекомендации при переходе на микроконтроллер ATmega169 перечислены в конце данного документа.

Клавиатура подключается к двум 8- битным портам AVR микроконтроллера. Один порт (порт D) настроен на работу всех линий в качестве выходов и подключен к строкам клавиатурной матрицы. Другой порт (порт C) настроен на работу всех линий в качестве входов и подключен к столбцам клавиатурной матрицы. Подробнее это можно увидеть на рисунке 2. При сканировании клавиатурной матрицы порт, используемый как выходной, должен удерживать выходы в низком состоянии, а порт, используемый как входной должен иметь встроенные подтягивающие к питанию резисторы.

Описываемое устройство использует первую линию порта Е для формирования последовательного кода, соответствующего коду нажатой кнопки. Данные передаются при помощи встроенного UART, использование которого описанного в примере применения AVR306.

При обычном нажатии формируется скан-код, значение которого лежит в диапазоне от 0 до 63 (8 строк * 8 столбцов). Нажатие кнопки вызова альтернативной функции также формирует обычный скан-код, но кроме этого устанавливаются соответствующие флаги альтернативных функций. Эти флаги состояния хранятся в глобальной переменной.

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

Другая глобальная переменная используется для передачи приложению скан-кода вместе с флагами. Шесть младших бит используются для передачи кода (от 0 до 63), а старший значащий бит (СЗБ) указывает на изменение состояния. Драйвер клавиатуры устанавливает этот бит при нажатии кнопки. Приложение опрашивает этот бит и сбрасывает его после считывания скан-кода. Глобальный байт и скан-слово показаны на рисунке 5.


Рисунок 5. Расширенный скан-код

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

Модуль инициации и основная программа

На рисунке 6 показан модуль инициализации и основная программа. Сброс флагов альтернативных функций и глобальных переменных, а так же инициализация портов описаны выше. Если не требуется производить никакой обработки, то выбирается Idle режим сна.


Рисунок 6. Модуль инициации и основная программа

Основной модуль декодера клавиатуры Декодер клавиатуры представляет собой подпрограмму обработки прерывания по изменению состояний портов. Сначала выбирается Idle режим сна, позволяющий AVR микроконтроллеру активизироваться по переполнению таймера, что невозможно при нахождении микроконтроллера в Power-down режиме сна. Таймер устанавливается на формирование прерывания через 5 мс, что вполне достаточно для окончания переходных процессов сигналов на выводах. В течение этого времени задержки основная программа восстанавливает управление и может активизировать режим сна. По окончании времени задержки вызывается процедура обработки нажатия кнопок. Эта функция завершает определение кода нажатой кнопки. По окончании ее на линиях портов всех строк устанавливается низкий уровень и активизируется Power-down режим сна, выход из которого возможен по нажатию на кнопку. Блок-схема этого программного модуля показана на рисунке 7.

Рисунок 7. блок-схема основного программного модуля декодера клавиатуры

Сканирование клавиатуры (обработка нажатия кнопок) На рисунке 8 приведена блок-схема подпрограммы сканирования клавиатуры. Сначала сканируется результат по столбцам. Три младших бита скан-кода (столбцы) увеличиваются до тех пор, пока не будет найден низкий уровень на линии столбца. После этого происходит инвертирование направленности линий портов и сканирование повторяется. При этом производится поиск низкого уровня на линиях строк. После этого вызывается подпрограмма обработки скан-кода.


Рисунок 8. Блок-схема подпрограммы сканирования клавиатуры

Сначала функция обработки скан-кода копирует сформированный скан-код в глобальную переменную. После этого скан-код сравнивается с кодами кнопок альтернативных функций и формируются соответствующие флаги альтернативных функций. Эти флаги копируются в глобальную переменную. Если нажатая кнопка не является альтернативной, то флаги всех одновибраторных альтернативных функций сбрасываются. Наконец, устанавливаются новые флаги. Блок схема этой функции приведена на рисунке 9.


Рисунок 9. Блок-схема функции обработки скан-кода

Тестовый пример применения myCellPhone

Существует тестовый пример применения, в котором реализована клавиатурная матрица, напоминающая клавиатуру сотового телефона. Конечные символы в нем передаются по USART интерфейсу. Используя клавиатурную матрицу 4 x 4 можно сформировать все цифры и символы, которые можно обеспечить при помощи еще четырех кнопок вызова альтернативных функций. Три кнопки используются для выбора альтернативной функции каждой основной кнопки, а четвертая выполняет роль кнопки Caps Lock (переключение между верхним или нижним регистрами).

Для преобразования скан-кодов в кодовые комбинации, соответствующие кодам нажатых кнопок с учетом кнопок альтернативных функций, используется таблица преобразования. Скан-код может быть использован и для сканирования клавиатурной матрицы 8 x 8. Таким образом, таблица должна иметь 8 входов на строку, притом, что используется только 4 кнопки в каждой строке. Таким образом, при увеличении количества столбцов клавиатурной матрицы изменения размера программы не произойдет.

Размер кода прикладной программы и временные параметры

Размеры кодов подпрограмм различных функций обработки клавиатурной матрицы приведены в таблице 1.

Таблица 1. Размеры кодов подпрограмм различных функций обработки клавиатурной матрицы

В таблице 2 приведены длительности выполнения различных действий микроконтроллером ATmega162, работающем на частоте 8 МГц. Здесь приведены последовательности действий от пробуждения при обнаружении нажатия кнопки до входа в режим сна после обработки нажатых кнопок.

Таблица 2. Длительности выполняемых последовательностей действий

Если не учитывать Power-down режим сна, то видно, что большую часть времени микроконтроллер работает в Idle режиме сна. В активном режиме микроконтроллер находится всего 0.3 мс, что составляет около 0.5 % от общего времени. Относительное время нахождения в различных рабочих режимах приведено в таблице 3.

Таблица 3. Потребление и относительное время нахождения микроконтроллера в различных рабочих режимах

Если предположить, что кнопки нажимаются раз в 10 минут, то среднее потребление составит всего 2 мкА.

Рассуждения об использовании других микроконтроллеров

Единственное отличие при использовании микроконтроллеров ATmega162 и ATmega169 состоит в том, что у них должны использоваться разные порты для подключения клавиатурной матрицы. ATmega162 использует порт C, в то время как у ATmega169 должен использоваться порт Е. Это вызвано тем, что у них различные порты имеют прерывание по изменению состояния линий. ATmega162 имеет функцию формирования прерывания по изменению состояния линий порта С, а ATmega169 - по изменению состояния линий порта Е. Если необходимо использовать другие альтернативные функции этих портов, то необходимо модифицировать приложение таким образом, чтобы использовать для подключения клавиатурной матрицы другой порт, имеющий функцию формирования прерывания по изменению состояния линий.

Также обратите внимание, что для активизации режима сна ATmega169 использует SMCR регистр.

При использовании других микроконтроллеров понадобятся дополнительные внешние компоненты и изменение используемого прерывания. Использование таких микроконтроллеров для обработки клавиатурной матрицы 4х4 описано в примере применения AVR240. Остальные функции описанного примера применения в изменениях не нуждаются.