Decada
Автор: WildCat
2010-02-22

Подключаем клавиатуру к МК

Большинству небольших приложений на микроконтроллерах требуется одна или несколько кнопок для осуществления ввода данных пользователем. Но когда ваши проекты становятся более сложными, им может потребоваться небольшая клавиатура. Обычно можно приобрести готовую клавиатуру, встречаются варианты 3x4 или 4x4 клавиши, и почти всегда клавиши в ней соединены по схеме матрицы:



Матрица применяется потому, что для её подключения необходимо минимальное число линий ввода-вывода. Например, для клавиатуры 4x4 из 16 выключателей нужно 16 линий ввода. Гораздо более разумным решением было бы организовать их в 4 строки по 4 выключателя, использовав тем самым всего 8 линий (один порт контроллера!)
Но как использовать такую клавиатуру? Существует много решений. Самое распространённое - подключить матрицу на один порт, подключив строки к старшим разрядам, а столбцы - к младшим. Но мы столкнёмся с небольшой проблемой - при нажатии любой клавиши должно возникать прерывание, и контроллер должен считывать состояние клавиатуры. PIC контроллер вполне справится с такой задачей, но наш AT90S2313 имеет на борту всего два внешних прерывания. Проблему можно устранить, добавив 4 диода и подтягивающие резисторы, чтоб сделать элемент "ИЛИ" на входе Int0:


470-омные резисторы защитят контроллер от короткого замыкания питания на землю. Это возможно в теории, но вы можете сделать макет и без них.
На входе Int0 висит подтягивающий резистор 10 кОм к плюсу питания. Мы назначим четыре старших бита в PortB на выход, установив на них низкий уровень. Младшие 4 бита будут работать как входы, на них сделаем высокий уровень. Теперь, если нажать клавишу, возникнет соединение между каким-либо столбцом и строкой. Теперь на линии строки появится низкий уровень. Также низкий уровень появится и на строке с диодами, сработает элемент "ИЛИ" и на входе Int0 также появится низкий уровень и вызовет прерывание.
В подпрограмме обработки прерывания мы опрашиваем состояние строк, чтобы узнать, на какой из них нажата клавиша. Теперь мы переназначаем старшие биты на вход, а младшие на выход и точно таким же образом определяем, на каком столбце нажата клавиша. После этого выжидаем время "антидребезга". Зная теперь строку и столбец, несложно догадаться, что клавиша нажата на их пересечении. Делаем необходимые выводы, устанавливаем нужные параметры, и возвращаем состояние пинов порта к начальным значениям.



Конечно, указанное расположение строк и столбцов сугубо условно, вы сами можете разместить их так, чтобы сократить число линий и упростить управление.
Приведем пример программы для работы с клавиатурой:
keyboard-int.bas

$regfile = "2313def.dat"
$crystal = 4000000

$baud = 9600

Const Debouncetime = 150

Config Pind.6 = Output
Config Pind.2 = Input

Config Int0 = Falling
Dim Wtime As Byte
Dim Keycoderow As Byte
Dim Keycodecol As Byte
Dim Keycode As Byte
Dim Keychar As String * 1

On Int0 Button

'старшая половина порта на выход, младшая - на вход
Ddrb = &B11110000
Portb = &B00001111
Wtime = 255

Print "ready..."

Enable Interrupts
Enable Int0

Do
  Set Portd.6
  Waitms Wtime
  Reset Portd.6
  Waitms Wtime
Loop

Button:
  Waitms Debouncetime
  'опросим ноги порта B и определим, на которой низкий уровень
  Keycoderow = Pinb
  'поменяем назначение входов/выходов половин порта
  Ddrb = &B00001111
  Portb = &B11110000
  'выждем антидребезг
  Waitms 1
  'определим, на каком столбце низкий уровень
  Keycodecol = Pinb
  'вернем состояние порта к первоначальному
  Ddrb = &B11110000
  Portb = &B00001111
  'получим код клавиши исходя из полученных значений
  Select Case Keycoderow
    Case 7 : Keycode = 0
    Case 11 : Keycode = 4
    Case 13 : Keycode = 8
    Case 14 : Keycode = 12
    Case Else : Keycode = 99
  End Select
  Shift Keycodecol , Right , 4
  Select Case Keycodecol
    Case 7 : Keycode = Keycode + 0
    Case 11 : Keycode = Keycode + 1
    Case 13 : Keycode = Keycode + 2
    Case 14 : Keycode = Keycode + 3
    Case Else : Keycode = Keycode + 99
  End Select
  'неверный код клавиши из-за дребезга...
  If Keycode > 15 Then Keycode = 16
  Print Keycoderow ; " " ; Keycodecol ; " " ; Keycode
  Keychar = Lookupstr(keycode , Keycodes)
  Print Keychar
  Gifr = 64
Return

End

Keycodes:
Data "1" , "2" , "3" , "A" , "4" , "5" , "6" , "B" ,
Data "7" , "8" , "9" , "C" , "R" , "0" , "E" , "D" , "?"
Преобразование кода клавиши в соответствующий символ находится в блоке данных Keycodes. Если в вашей клавиатуре иное расположение клавиш, достаточно изменить блок данных.
Программа отсылает полученный с клавиатуры символ в терминал ПК через интерфейс RS-232. Так как все линии порта B заняты клавиатурой, нам пришлось отключить ЖКИ.

Обратите внимание: в Bascom есть команда Getkbd, которая умеет самостоятельно опрашивать клавиатуры 3x4 или 4x4. Но она не работает внутри подпрограммы прерывания, её можно выполнять только внутри основного цикла.

WildCat
2010-02-22

Желаете купить табак для кальяна?
CMS версия 3.0.0 by Demson