Статья №5


В  этой  статье  мне  бы  хотелось  познакомить  читателей  с  подключением  к  микроконтроллерам  клавиатуры. Дело  в  том, что  обычно  большинству  схем  на  микроконтроллерах  для  ввода  данных  требуется  одна  или  несколько  кнопок. Но, когда  проекты  становятся  сложнее,   может  возникнуть  потребность  в  применении  небольшой  клавиатуры. Встречаются  варианты  клавиатур  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:  
Stro = PORTB 
     Инвертируем  настройки  порта – сделаем  столбцы  РВ3 – РВ7  входами  и  включим  их  подтяжку, а  строки  РВ0 – РВ3 – выходами:
 
DDRB = &B00001111
PORTB = &B11110000
 
     Теперь  при  нажатой  кнопке  «1»  порт  будет  иметь  значение  11100000, которое  является  кодом  столбца. Считаем  этот  код  в  переменную  Col:
Col = PORTB
     Сумма  переменных  Stro  и  Col  даст  нам  код  кнопки:
Code = Stro + Col       ‘ 11100111 – код  кнопки  «1»
      Далее  необходимо  создать  два  блока  данных:
В  первом  располагаются  коды  кнопок  клавиатуры (метка – Codbytes). Во  втором  блоке  (метка – Keycodes)  находятся  названия  кнопок, которые  должны  располагаться  в  соответствии  с  кодами  кнопок  первого  блока  (в  том  же  порядке).
     Полученный  код  (Сode)  в  цикле  сравнивается  с  кодами  кнопок  первого  блока  данных  и  при  их  равенстве  определяется  индекс  кода  и, следовательно , индекс  названия  кнопки:  I1 = I +1
     Название  нажатой  кнопки  определяется  с  помощью  функции  Lookup:
                               Keycode = Lookupstr (Index1, Keycodes)
      Вывод  в  терминал  названия  нажатой  кнопки  происходит  с  помощью  уже  описанной  прцедуры:
                               Print “Keycode=”; Keycode
     Далее, после  выхода  из  цикла, осуществляется  начальная  установка  состояния  порта В  и   выход  из  подпрограммы.
     Блок – схема  программ  приведены  на  Рис.4. и Рис.5.
 
Рис.5 - Блок-схема программы KEY2   
Текст  программы  приводится  ниже.
 
$regfile = "attiny2313a.dat"       'настройки
$crystal = 4000000
$hwstack = 40
$swstack = 16
$framesize = 32
$sim

 Config Debounce = 75              'задержка входного сигнала
 Config Pind.6 = Output            'конфигурирование выводов
 Config Pind.2 = Input
 Config Pind.3 = Output

 Config Int0 = Falling             'внешнее прерывание по спаду импульса

 Dim Wtime As Byte                 'объявление переменных
 Dim Stro As Byte
 Dim Col As Byte
 Dim Code As Byte
 Dim Codbyte(16) As Byte
 Dim Keycode As String * 4
 Dim Index As Integer
 Dim Index1 As Integer

 On Int0 Button                    'подпрограмма прерывания


 Ddrb = &B11110000                 'PB0...PB3 -входы,остальные - выходы
 Portb = &B00001111                'подтяжка PB0...PB3
 Wtime = 100                       'величина задержки

 Print "ready..."                  'вывод слова на RS-232

 Enable Interrupts                 'разрешение прерываний
 Enable Int0

 Do
   Set Portd.6                     'включение светодиода
   Waitms Wtime                    'задержка
   Reset Portd.6                   'выключение светодиода
   Waitms Wtime
 Loop



 Button:                           'подпрограмма обработки прерывания
 Waitms Wtime
 Stro = Portb                      'считывание значий строк (младшие биты порта В)
 Ddrb = &B00001111                 'инвертирование значений полубайтов порта В
 Portb = &B11110000
 Col = Portb                       'считывание значений столбцов (старшие биты порта В)
 Code = Stro + Col                 'определение кода нажатой кнопки
 Restore Codbytes
 For Index = 1 To 16
 Index1 = Index - 1
 Read Codbyte(index)               'считывание кодов кнопок из блока данных
 If Code = Codbyte(index) Then     'сравнение  полученного кода с кодами блока данных
 Print "Codbyte:" ; Codbyte(index) 'передача в терминал кода нажатой кнопки
 Keycode = Lookupstr(index1 , Keycodes)       'определение названия нажатой кнопки
 Print "Keycod=" ; Keycode         'передача  в терминал названия нажатой кнопки
 End If
 Next Index
 Ddrb = &B11110000                 'установка начальнго состояния портаВ
 Portb = &B00001111

 Return                            'возврат из подпрограммы прерывания

 End                               'end program

 Codbytes:
 Data &B11100111 , &B11010111 , &B10110111 , &B01110111 , &B11101011 , &B11011011 , &B10111011 , &B01111011 , &B11101101 , &B11011101 , &B10111101 , &B01111101 , &B01111110 , &B11101110 , &B11011110 , &B10111110 , &B01111110
 Keycodes:
 Data "1" , "2" , "3" , "A" , "4" , "5" , "6" , "B" , "7" , "8" , "9" , "C" , "*" , "0" , "#" , "D"      

     Результаты  симуляции  программы  приведены  на  Рис.6.  Более  подробно  о  процессе  симуляции  будет  рассказано  в  следующей  статье.
 

  Рис.6 
Сама  программа  находится  в  приложении 1  настоящей  статьи.