16 кнопочная клавиатура stm32 arduino подключение. Подключение матричной клавиатуры к Arduino. Для чего нужна матричная клавиатура

Отладочная плата F103C8T6 на базе STM32 по параметрам значительно опережает аналогочные по размеру Arduino Nano или Leonardo, а по скорости близка к Arduino DUE. Есть интерес попробовать, но у новичка могут возникнуть трудности с первым запуском и программированием данной платы. Теперь есть возможность заливать скетчи через Arduino IDE. Подробности далее...

  1. Отличия STM32F103C8T6 от Arduino Nano v3.0
  2. Подготовка железа
  3. Подготовка ПО
  4. Закачка скетча (blink) в плату

1. Отличия STM32F103C8T6 от Arduino Nano v3.0

2. Подготовка железа

Для работы нам понадобится:

  • Сама плата STM32F103C8T6
  • Соединительные провода Dupont мама-мама

Для активации режима программирования на плате STM следует преставить перемычки: первая на 1, вторая на 0.

Конвертер FTDI переключить на питание 3.3 Вольта (перемычкой/джампером)

Соединить проводами плату (П) и конвертер (К):

П(A9) -> K(RX)

П(А10) -> К(TX)

П(GND) -> K(GND)

П(3.3) -> K(VCC)

3. Подготовка ПО

  1. Скачать дополнение для Arduino IDE , которое будет поддерживать платы STM32
  2. Распаковать архив в папаку HARDWARE, которую можно найти в папке вашей Arduino IDE
  3. Запустить Arduino IDE (или перезапустить если была открыта) и проверить появился ли раздел STM32 Boards в списке Плат

4. Закачка скетча (blink) в плату

В папке которую мы распаковали в п.3.б заходим по следующему пути: Arduino_STM32\examples\Digital\Blink\ и через Arduino IDE открываем файл blink.ino либо можете взять текст отсюда:

void setup () { // initialize digital pin PB1 as an output. pinMode (PC13 , OUTPUT ) ; } // the loop function runs over and over again forever void loop () { digitalWrite (PC13 , HIGH ) ; // turn the LED on (HIGH is the voltage level) delay (1000 ) ; // wait for a second digitalWrite (PC13 , LOW ) ; // turn the LED off by making the voltage LOW delay (1000 ) ; // wait for a second }
  • Выбрать плату Generic STM32F103C series
  • Выбрать Variant: (20k RAM. 64k Flash)
  • Выбрать Upload method: "Serial"
  • Выбрать Порт: (порт сооответствующий FTDI конвертеру)

Жмем кнопку Вгрузить и результат сразу должен быть виден.

«. Сегодня подключаем матричную клавиатуру к плате 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 , где в скобках задается название переменной и «указание» ей. Можно таким образом написать определенные команды для каждой кнопки и управлять большим количеством светодиодов или создать команду для включения всех светодиодов сразу.

  • Tutorial

Хотите прокачать ваши Arduino проекты? Заставить их работать быстрее, измерения и регулировку сделать точнее, ну и добавить баги(с новыми девайсами они неизбежны). Тогда эта статья для Вас.

Arduino тема всё больше захватывает умы человечества, но рано или поздно мы встречаемся с тем, что нам чего-то не хватает, например бюджета/размеров/ пинов портов/разрядности/производительности… Как говорил один мудрый человек - «Кто хочет, тот ищет возможности, кто не хочет - ищет причины».

Хорошие люди это понимают, и потихоньку начинают приобщать STM32 к ардуино теме , ибо восьмибитные AVR микроконтроллеры, на которых основано немало ардуино плат, не всегда могут справиться с поставленными задачами.

Краткое изложение данной статьи в видео формате:



Ладно, меньше лирики и ближе к теме. В этой статье, я буду рассматривать дешёвую отладочную плату, которая основана на базе микроконтроллера :

Для начала, сравним основные параметры STM32 платы, и её аналога по цене - Arduino Nano V3.0:

  • Рабочая частота 72 МГц, против 16 у ардуино;
  • Объем Flash памяти 64 Кбайта, против 32;
  • Оперативной памяти, она же RAM(где хранятся переменные), у STM32 целых 20 Кбайт, у ардуинки всего лишь 2;
  • Быстрый 12-ти битный АЦП, в то время как у Arduino плат, что на базе AVR микроконтроллеров(это как правило большинство) используется 10-ти битный. Это означает, что в случае STM32, функция analogRead(*); будет возвращать 0..4095 против 0..1023, что в первом случае ведёт к более точным измерениям;
  • 16-ти битный аппаратный ШИМ, против 8-ми у Arduino плат, то есть, функция analogWrite(*); pwmWrite(*); может принимать значение 0..65535, против убогих 0..255. Это позволит ещё точнее управлять нашими двигателями, сервами и прочими девайсами, которые рулятся при помощи ШИМ;
  • Аппаратная работа с USB, чем не может похвастаться не одна Arduino плата стоимостью менее 2 долларов;
  • Напряжение питания - от 2 до 3.6В(прямо таки заточено под 2 AA батарейки), против 2.7...5В у ардуино плат;
  • Цены на момент написания статьи - 1.9 доллара против 1.8(алиэкспресс).
Очевидно, что отладочная плата на базе STM32 выигрывает по всём параметрам у Arduino Nano, исключением является разве что стоимость, но согласитесь 10 центов - хорошая цена за большую производительность, а про периферию, которой нафарширован STM32, так я вообще молчу, чего только стоят DMA или интегрированные в микроконтроллер часы реального времени.

Всё это в сумме делает данную плату крайне привлекательной во всём, кроме одного - новичку, как например мне, тема STM32 кажется слишком затратной по времени, есть целые сайты посвящённые программированию этих микроконтроллеров. А вот если подружить STM32 с Arduino IDE, то порог вхождения опускается до крайне низкого уровня. Хотя, как говориться, «В каждой бочке мёда, есть ложка дёгтя», но об этом чуть ниже.

Приступим к подготовке платы, для работы с Arduino IDE. Первое что необходимо сделать - залить в микроконтроллер специальный загрузчик, который позволит прошивать плату через аппаратный USB, причём прямо из среды разработки. Для этого необходимо перевести верхний джампер(он же «BOOT0»), в положение «1»:

Для чего нужны BOOT0 и BOOT1 джамперы

Дело в том, что в STM32 с завода прошит, в так называемую системную память(system memory), специальный загрузчик, который позволяет прошивать плату через самый обычный USB to UART переходник, не прибегая к специфическим программаторам типа ST-Link V2 .


Дальше нам понадобиться переходник с USB на UART. Стоит помнить, что STM32, это 3.3 В логика , совместимость с 5-ти вольтовой не гарантируется, поэтому рекомендовано использовать USB to UART, у которого есть возможность выбора режимов работы с 3.3/5В логикой. Я использовал дешёвый переходник на базе CH340G:


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

Плату подключил к USB to UART переходнику следующим образом:

G <-> GND;
5V <-> 5V;
PA10 <-> TXD;
PA9 <-> RXD.


* PA10/PA9 на плате подписаны просто как A10/A9 - эти порты являются первым аппаратным USART"ом, всего их на плате 3, так же тут 2 аппаратных I2C и 2 SPI.

Ради удобства запитал плату от 5 В, для питания от 3.3 В на плате есть пин «3.3». Внимание, 5 В может запросто вывести микроконтроллер из строя , так что уделите должное внимание подключению.

Качаем, устанавливаем и запускаем Flash Loader Demonstrator (есть в архиве к статье):

Выбираем номер COM-порта нашего переходника, в моём случае это COM43, потом нажимаем «Next»:

Так как у меня микроконтроллер новый, ещё муха не сидела на него никто ничего не записывал(разумеется кроме самого производителя), то тут по умолчанию стоит защита от чтения, программа нас предупреждает, что если нажать кнопку «Remove protection», Flash память будет очищена, то есть если бы там была какая-то прошивка - она удалится. В моём случае там ничего полезного нет, так что смело жму. Далее вижу следующее:

Жмём «OK»:

Так как моя отладочная плата основана на микроконтроллере STM32F103C8 - здесь 64 Кбайт Flash памяти, есть ещё STM32F103CB микроконтроллер, где в два раза больше Flash.

Опять «Next», и видим следующее окно:

Выбираем «Download to device» и жмём на "...":

Меняем тип файлов на *.bin и открываем файл «generic_boot20_pc13.bin»(тоже присутствует в архиве) который можно взять из проекта STM32duino-bootloader .

Потом надо скачать, для среды разработки Arduino IDE, специальное STM32 ядро (так же есть в архиве к статье). Тут есть один нюанс, на момент написания статьи, ядро не работает на версиях среды разработки свыше 1.6.5 , у меня стоит 1.6.5-r5 которую .
Проверенна работоспособность ядра на .

В моём случае полный путь выглядит вот так - «C:\Users\RSK\Documents\Arduino\hardware»

Разумеется, что система устройство определить не сумеет, поэтому надо ещё установить драйвера на плату. Заходим в папку «Мои Документы\Arduino\hardware\Arduino_STM32\drivers\win»(или «drivers\win», в случае архива к статье), и запускаем от имени администратора файл «install_drivers.bat»:

После этого верхний джампер(тот что «BOOT0»), переводим в положение «0» и подключаем плату к компьютеру через microUSB кабель:

Она должна в диспетчере устройств определиться или как «Maple DFU» или «Maple Serial (COM*)»:

Не совсем понятно почему после первого подключения плата определяется по-разному, на разных компьютерах, но не суть, приступаем к настройке Arduino IDE.

Здесь нужно установить ядро для платы Arduino Due. Выбираем последнюю версию и нажимаем «Install»:

Потом Инструменты -> Плата -> «Generic STM32F103C», дальше Variant: «STM32F103C8 (20k RAM. 64k Flash)», Upload Method: «STM32duino bootloader», Порт - номер COM-порта платы, вообщем всё как на скрине:

Всё, плата готова к прошивке и программированию в среде разработки Arduino IDE. Давайте прошьём какой-то скетч из примеров, которые «вшиты» в ядро, заходим Файл -> Папка со скетчами -> hardware -> Arduino_STM32 -> STM32F1 -> libraries -> A_STM32_Examples -> Digital -> Blink:

Классический «Hello World» в мире микроконтроллеров. Изменяем PB1 на PC13, так как светодиод, что на плате, подключен к этому порту:


* К стати, загорается он по низкому уровню на ножке PC13.

Нажимаем кнопку «Вгрузить», после прошивки среда разработки выдаст что-то типа:

«Done!
Resetting USB to switch back to runtime mode
error resetting after download: usb_reset: could not reset device, win error: Не удается найти указанный файл.».

Но прошивка то загрузилась успешно, хотя не всегда так, иногда Arduino IDE выдаёт другие сообщения.

Couldn"t find the DFU device

Когда видите, сообщение типа:

«dfu-util - © 2007-2008 by OpenMoko Inc.
Couldn"t find the DFU device:
This program is Free Software and has ABSOLUTELY NO WARRANTY»

Это означает, что плату прошить не удалось.

Searching for DFU device ...

Когда среда разработки выдаёт:

«Searching for DFU device …
Assuming the board is in perpetual bootloader mode and continuing to attempt dfu programming...»

И больше ничего не происходит, попробуйте в этот момент перезагрузить плату клацнув кнопку ресет. По аналогии это как с Arduino Pro Mini.

А теперь про «ложку дёгтя», о которой я писал вначале статьи, почему-то не всегда получается прошить плату в среде разработки, даже больше, она не всегда определяется компьютером. Я для себя это решил следующим образом, перед тем как загрузить прошивку(перед нажатием кнопки «Вгрузить»), клацаю «Reset» на плате, и после прошивки, ещё раз перезагружаю плату. В этом случае процент вероятности, что плата прошьется, равен 99%. Непонятно почему работает именно так, но факт. Думаю, что рано или поздно этот косяк поправят, и всё будет автоматом перезагружаться как нужно. А чтобы это быстрее поправили, надо чтобы комьюнити этой замечательной STM32 отладочной платы росла, поэтому делитесь этой статьей с друзьями, особенно с друзьями программистами.

По поводу распиновки:

Кликабельно

Лучшее что мне удалось найти, это распиновка самого микроконтроллера(открывайте в новой вкладке):


(с) www.stm32duino.com/viewtopic.php?p=11137

К порту нужно обращаться по полному имени, например:

digitalWrite(PB0, LOW);
analogWrite(PA8, 65535); pwmWrite(PA8, 65535);
analogRead(PA0);
LiquidCrystal lcd(PB0, PA7, PA6, PA5, PA4, PA3);

Ещё рекомендую зайти на сайт docs.leaflabs.com/docs.leaflabs.com/index.html там есть много чего интересного по теме программирования в Arduino IDE, правда на английском языке.

Я порылся в файлах ядра, и нашёл один интересный файл:
Documents\Arduino\hardware\Arduino_STM32\STM32F1\variants\generic_stm32f103c\board.cpp

Там прописаны все порты, которые поддерживают:

  • ШИМ, то есть функция analogWrite(); pwmWrite(); - PB0, PA7, PA6, PA3, PA2, PA1, PA0, PB7, PB6, PA10, PA9, PA8, а это далеко не все, которые размечены на распиновке чипа;
  • АЦП, аля analogRead(); - PB0, PA7, PA6, PA5, PA4, PA3, PA2, PA1, PA0.

Так что имейте это ввиду. Хотя этого более чем достаточно от платы, стоимостью в 1.9 доллара.

Ещё заметил, что пины PA12/PA11 подключены к D+/D- USB, их лишний раз лучше вообще не трогать, ибо чуть что, на кону не 2-х долларовый кусок стеклотекстолита с чипом, а материнская плата компьютера.

Схема отладочной платы:

Ну и на последок:

Линейка микроконтроллеров STM32 представляет собой достаточно интересный объект для изучения. Часто можно услышать мнение, что работа с ним сложна для начинающего и лучше браться за что – нибудь более простое. В этой статье мы постараемся показать, что микроконтроллеры STM32 не так страшны.

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

При работе, описанной в данной статье, использовалась отладочная плата STM32F4Discovery и матричная клавиатура, в нашем случае, имеющая 7 выводов. Среда разработки CoIDE 1.7.6.

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

Перед тем, как приступать к написанию программы, определимся с условными обозначениями:

  1. Выводы, к которым подключается клавиатура, разделены на две группы: сканирующие и питающие (рисунок 1). Сканирующие выводы работают на вход. Все питающие выводы по умолчанию установлены в нулевое состояние, но после первого сброса таймера TIM2 на выводе PA3 будет установлено напряжение логической «1», поэтому с некоторым приближением можно сказать, что на питающих выводах в момент времени, близкий к начальному, выставлена комбинация «1-0-0-0».
  2. По тексту программы обозначения выводов будут соответствовать рисунку 1, т.е. значения выводов PA0, PA1, PA2 при их опросе записываются в переменные a, b, c соответственно, для дальнейших операций с ними.
  3. Питающие выводы PA3 – РА4 имеют обозначения от 1 до 4, именно под такими номерами они упоминаются в тексте программы.

Рисунок 1 – Подключение клавиатуры

Перейдем к описанию алгоритма действия программы. После включения питания запускаются два таймера (TIM2 и TIM3), которые работают циклически, т.е. при завершении счета выполняются некоторые действия (эти действия прописаны в функциях обработчиках прерываний от таймеров TIM2 и TIM3) и отсчет начинается заново. По окончании первого отсчета таймера TIM2 на выводе РА3 появляется уровень логической «1», который каждый раз, при окончании счета этого таймера, смещается на одну позицию вниз. При этом микроконтроллер всегда «знает», на каком выводе в данный момент находится уровень напряжения логической «1», эта информация хранится в переменной out_state. Операцию по «сдвигу» логической «1» выполняет функция TIM2_IRQHandler (обработчик прерывания от таймера 2).

Таймер TIM3 при окончании каждого цикла сканирует состояние выводов РА0-РА2, записывая полученные результаты в переменные a, b и c. Затем, микроконтроллер сравнивает на каком из питающих выводов находится напряжение логической «1» (переменная out_state) и какой из выводов РА0 – РА2 имеет высокий логический уровень (переменные a, b, c). Эти действия выполняет функция TIM3_IRQHandler (обработчик прерывания от таймера 3).

При нажатии, например, кнопки «3», высокий логический уровень должен быть установлен на выводе РА3 и зарегистрирован на выводе PA0. При выполнении данного логического выражения микроконтроллер «поймет», что была нажата клавиша «3» и при нажатии этой кнопки выполнит предписанное ему действие, в нашем случае погасит все светодиоды, а затем зажжет зеленый светодиод.

Используемая процедура сравнения позволяет различать между собой одновременное нажатие одной, двух, трех и более клавиш (при доработке функции TIM3_IRQHandler) и присвоение такому событию определенного действия.

В данном примере, для того чтобы понять правильно или нет написана программа, использованы различные комбинации светодиодов, расположенных на плате, клавиша 5 – выключает все светодиоды.

Очень важно разобраться, какие выводы на клавиатуре соответствуют нажатым клавишам. Необходимо выделить строки и столбцы (деление на строки и столбцы в данном случае весьма условно, так как это зависит от формы и положения клавиатуры. Примем по умолчанию, что столбцы – это линия «3-6-9-#» и т.д., а строки – «3-2-1» и т.д.), т.к. столбцы соединяются со сканирующими выводами, строки – с выводами питания. Для правильного определения выводов на матричной клавиатуре необходимо подключить один из щупов мультиметра, находящегося в режиме прозвонки, к любому крайнему контакту, а второй щуп подключать к остальным контактам, одновременно нажимая на клавиши, расположенные в одном столбце. Если при нажатии на любую клавишу два вывода не прозваниваются – это значит, что они оба принадлежат к одной группе (строчных или столбиковых выводов). После того, как все выводы будут разбиты на две группы, можно переходить к определению порядка их размещения внутри групп. При этом, при фиксированном подключении к одному столбиковому выводу, необходимо менять контакты из второй группы нажимая одновременно с этим только клавиши, принадлежащие к одному столбцу.

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

Теперь поговорим об инициализации используемой периферии. В этом проекте используются порты A и D, как порты ввода-вывода, а так же таймеры TIM2 и TIM3. Листинг программы снабжен подробными комментариями по пунктам настройки периферии.

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

Для Arduino чаще всего используются такие клавиатуры:

Самыми распространенными являются 16 кнопочные клавиатуры 4x4. Принцип их работы достаточно прост, Arduino поочередно подает логическую единицу на каждый 4 столбцов, в этот момент 4 входа Arduino считывают значения, и только на один вход подается высокий уровень. Это довольно просто, если знать возможности управления портами вывода в Arduino , а так же портами входа/ввода.

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

Подключаем клавиатуру в любые порты ввода/вывода.

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

В программе будем вычислять нажатую кнопку и записывать её в Serial порт.
В данном методе есть один значительный недостаток: контроллер уже не может выполнять других задач стандартными методами. Эта проблем решается подключением матричной клавиатуры с использованием прерываний .

Int PinOut {5, 4, 3, 2}; // пины выходы int PinIn {9, 8, 7, 6}; // пины входа int val = 0; const char value { {"1", "4", "7", "*"}, {"2", "5", "8", "0" }, {"3", "6", "9", "#"}, {"A", "B", "C", "D"} }; // двойной массив, обозначающий кнопку int b = 0; // переменная, куда кладется число из массива(номер кнопки) void setup() { pinMode (2, OUTPUT); // инициализируем порты на выход (подают нули на столбцы) pinMode (3, OUTPUT); pinMode (4, OUTPUT); pinMode (5, OUTPUT); pinMode (6, INPUT); // инициализируем порты на вход с подтяжкой к плюсу (принимают нули на строках) digitalWrite(6, HIGH); pinMode (7, INPUT); digitalWrite(7, HIGH); pinMode (8, INPUT); digitalWrite(8, HIGH); pinMode (9, INPUT); digitalWrite(9, HIGH); Serial.begin(9600); // открываем Serial порт } void matrix () // создаем функцию для чтения кнопок { for (int i = 1; i <= 4; i++) // цикл, передающий 0 по всем столбцам { digitalWrite(PinOut, LOW); // если i меньше 4 , то отправляем 0 на ножку for (int j = 1; j <= 4; j++) // цикл, принимающих 0 по строкам { if (digitalRead(PinIn) == LOW) // если один из указанных портов входа равен 0, то.. { Serial.println(value); // то b равно значению из двойного массива delay(175); } } digitalWrite(PinOut, HIGH); // подаём обратно высокий уровень } } void loop() { matrix(); // используем функцию опроса матричной клавиатуры }

С использованием библиотеки считывание данных с цифровой клавиатуры упрощается.

#include const byte ROWS = 4; const byte COLS = 3; char keys = { {"1","2","3"}, {"4","5","6"}, {"7","8","9"}, {"#","0","*"} }; byte rowPins = {5, 4, 3, 2}; byte colPins = {8, 7, 6}; Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS); void setup(){ Serial.begin(9600); } void loop(){ char key = keypad.getKey(); if (key != NO_KEY){ Serial.println(key); } }