Алгоритм ввода данных с клавиатуры

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

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

Скан-код - это уникальный однобайтовый номер, присваиваемый каждой клавише[10]. Семь младших битов скан-кода – это собственно код клавиши, а старший бит используется для кодирования факта её нажатия (0) или отпускания (1). Такая система позволяет закодировать 128 различных клавиш (коды с "0" по "127" при нажатии и с "128" по "255" - при отпускании), что превышает потребности стандартной 101-клавишной клавиатуры.

Клавиатура подключена к линии IRQ1 контроллера прерываний, которой соответствует прерывание №9, и к порту ввода-вывода с адресом 60h, в который помещается скан-код последней нажатой (или отпущенной) клавиши. В процессе обмена данными с клавиатурой участвует также порт 61h, доступный как для чтения, так и для записи. Запись "1" в старший бит этого порта блокирует обмен данными с клавиатурой.

Дальнейшая реализация процесса ввода данных осуществляется программным обработчиком клавиатурного прерывания, который читает принятый в порт 60h скан-код клавиши, анализирует его значение и формирует соответствующие информационные структуры в области данных BIOS (таблица 2.3).

Таблица 2.3 - Блок данных BIOS, обслуживающий ввод с клавиатуры

Начальный адрес (hex) Длина, байт Назначение
0040:0017 Флаги клавиатуры
0040:0019 Текущее (накопленное) значение вводимого ASCII-кода символа (Alt + цифра)
0040:001A Адрес "хвоста" буфера клавиатуры
0040:001C Адрес "головы " буфера клавиатуры
0040:001E 20h Буфер клавиатуры (16 двухбайтовых элементов)

Флаги клавиатуры

Эти два байта в области данных BIOS формируются обработчиком прерывания №9 при нажатии и отпускании управляющих клавиш и клавиш-переключателей. Определенные биты этих флаговых байтов устанавливаются в "1" или "0" в зависимости от текущего состояния соответствующих клавиш или же от того, установлен или нет соответствующий режим.

Например, при нажатии клавиши <CapsLock> 6-й бит первого и второго флаговых байтов будет установлен в "1". При отпускании этой клавиши 6-й бит второго байта будет обнулен, а первый байт останется без изменений, что соответствует ситуации "установлен верхний регистр". После повторного нажатия и отпускания этой клавиши оба флаговых бита вернутся в исходное (нулевое) состояние.

В приведенных ниже диаграммах показана информационная структура флагов клавиатуры.

 
                = 1: Нажата правая клавиша <Shift>
  = 1: Нажата левая клавиша <Shift>
  = 1: Нажата клавиша <Ctrl>
  = 1: Нажата клавиша <Alt>
  = 1: Установлен режим "ScrollLock"
  = 1: Установлен режим "NumLock"
  = 1: Установлен режим "CapsLock"
  = 1: Установлен режим "Insert"
                                 

Рисунок 2.2 Структура 1-го "флагового" байта (0040:0017)

 
                = 1: Нажата правая клавиша < Ctrl >
  = 1: Нажата левая клавиша < Alt >
  = 1: Нажата клавиша < SysReq >
  = 1: Установлен режим " Pause "
  = 1: Нажата клавиша <ScrollLock>
  = 1: Нажата клавиша <NumLock>
  = 1: Нажата клавиша <CapsLock>
  = 1: Нажата клавиша <Insert>
                                 

Рисунок 2.3 Структура 2-го "флагового" байта (0040:0018)

Буфер клавиатуры

Буфер клавиатуры - это линейная область ОЗУ, в которую программа-обработчик прерывания №9 записывает данные об очередной нажатой символьной клавише, а прикладные программы считывают эти данные для дальнейшего использования. Для каждого нажатия клавиши в буфере зарезервировано по два байта: один (младший) байт для скан-кода клавиши, другой (старший байт) - для ASCII-кода символа, соответствующего этой клавише.

В первых PC/XT поддерживался буфер клавиатуры фиксированной длины 32 байта, который располагался в диапазоне адресов с 0040:001Eh по 0040:003Eh. Такой буфер рассчитан на регистрацию 16 последовательных нажатий клавиш.

В PC/AT адрес начала буфера (смещение относительно сегмента 0040h) указан в ячейке 0000:0480h, а адрес конца буфера - в ячейке 0000:0482h. Обычно эти ячейки содержат значения соответственно 001Eh и 003Eh, при этом размер и расположение буфера клавиатуры PC/AT аналогичны PC/XT.

При нажатии символьной клавиши обработчик прерывания вычисляет значение кода ASCII по ее скан-коду (с учетом текущего состояния флагов клавиатуры) и записывает эти коды в два соседних байта буфера.

Процесс записи данных в буфер клавиатуры и чтения данных из буфера регулируется двумя указателями. Двухбайтовое слово по адресу 0040:001Сh содержит адрес (смещение относительно сегмента 0040h) "головы" буфера, то есть указывает обработчику прерывания, куда следует записать пару кодов очередной нажатой клавиши, а двухбайтовое слово по адресу 0040:001Аh содержит адрес "хвоста" буфера, то есть указывает прикладной программе, откуда следует прочитать пару кодов первой из еще не прочитанных клавиш.

В исходном состоянии значения этих указателей одинаковы и равны 001Eh. После завершения каждой операции записи данных в буфер программа-обработчик 9-го прерывания инкрементирует (увеличивает на два) значение "головы", а программа, читающая буфер, соответственно инкрементирует значение "хвоста", – таким образом, при вводе данных с клавиатуры хвост буфера постоянно "догоняет" голову. Буфер клавиатуры организован циклически, то есть при достижении соответствующим указателем конца буфера этот указатель программно устанавливается в начало буфера.

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

При прямом вводе кода символа пользователь, удерживая нажатой клавишу <Alt>, набирает ASCII-код символа (в десятичной системе счисления) на дополнительной цифровой клавиатуре. При этом обработчик 9-го прерывания последовательно суммирует вводимый пользователем код (с учетом разряда числа) и сохраняет промежуточные результаты суммирования в ячейке 0040:0019h, пока клавиша <Alt> остается нажатой. После отпускания клавиши <Alt> результат суммирования переписывается из ячейки 0040:0019h в буфер клавиатуры, а сама эта ячейка обнуляется. Естественно, в этом случае соответствующий байт скан-кода в буфере клавиатуры остается нулевым.

Факты нажатия управляющих клавиш <Shift>, <Ctrl>, <Alt>, <ScrollLock>, <NumLock>, CapsLock>, <SysReq> или <Pause>, а также факты отпускания любой клавиши никак не отражаются на состоянии буфера клавиатуры. При нажатии других "несимвольных" клавиш в буфер попадает только скан-код, а байт кода символа остается нулевым.

Учебные задания

Методические указания

Установите режим "командная строка" (сеанс MS DOS).

Загрузите программы Calc.com, Peek.com и Help.exe (в указанном порядке).

Найдите в электронном справочнике Help разделы, описывающие ASCII-коды символов и Scan-коды клавиш. Ознакомьтесь с содержимым указанных разделов.

Не "закрывая" программы Help, активизируйте программу Peek (тройным нажатием левой клавиши <Alt>) и приступайте к выполнению учебных заданий.

В любой момент Вы сможете переключиться на работу с программой Help, нажав клавишу <Esc>, и затем вновь активизировать программу Peek тройным нажатием клавиши <Alt>.

Задание 1.Исследуйте процесс изменения состояния "флаговых" байтов в процессе манипулирования управляющими клавишами Shift, Ctrl, Alt, CapsLock, NumLock. По результатам эксперимента составьте таблицы, аналогичные приведенным на рисунках 1 и 2. Результаты представьте в шестнадцатеричном и двоичном форматах.

Задание 2.Установите режим "верхний регистр", не нажимая клавиши <CapsLock>. Попытайтесь отменить установленный режим с помощью этой клавиши. Проведите аналогичный эксперимент с клавишей <NumLock>. Прокомментируйте результаты эксперимента.

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

Задание 4.Введите символы "G", "g", "П" и "п". Определите состояние указателей головы и хвоста буфера клавиатуры после каждого нажатия на клавишу. Определите ASCII-коды введенных символов и Scan-коды соответствующих клавиш. Результаты представьте в шестнадцатеричной, десятичной и двоичной системах счисления. Выполните аналогичные действия для другой символьной клавиши.

Задание 5.Введите символы, указанные в предыдущем задании, прямым набором их ASCII-кодов при нажатой клавише <Alt>. Зафиксируйте промежуточные состояния ячейки с адресом 0040:0019h после ввода каждой очередной цифры ASCII-кода символа, а также состояние этой ячейки и соответствующих ячеек буфера клавиатуры после отпускания клавиши <Alt>. Прокомментируйте результаты.

Задание 6.Введите прямым набором символ с ASCII-кодом "1234". Прокомментируйте результат ввода.

Задание 7.Введите прямым набором "управляющие символы" (ASCII-коды от 0 до 31). Используя электронный справочник HELP, определите комбинации клавиш (Ctrl+клавиша), используемых для ввода управляющих символов.

Задание 8.Используя электронный справочник HELP и технологию прямого набора кодов символов, составьте таблицу ASCII-кодов символов русского алфавита и символов псевдографики.

Контрольные вопросы

Каковы основные функции контроллера клавиатуры ?

Какие манипуляции с клавишами не приводят к изменению состояния буфера клавиатуры ?

В каких случаях значения указателей "головы" и "хвоста" буфера клавиатуры совпадают ?

Как может возникнуть ситуация "переполнение буфера клавиатуры"? Какова реакция компьютера на такую ситуацию ?

Контрольная работа №2

Задача 2.1.Объясните понятия "линейный адрес" и "сегментный адрес". Опишите алгоритм работы сумматора адреса.

Задача 2.2.Определите линейные и сегментные адреса по данным приведенной ниже таблицы. Результаты представьте в шестнадцатеричной и двоичной системах счисления. Определите функциональное назначение соответствующих областей памяти ПК.

Линейный адрес Сегментный адрес Область памяти
  0000:010Ch  
00462h    
  0040:0002h  
0041Ah    
     
  B800:00CDh  

Задача 2.3.Опишите алгоритм работы программы обработки прерывания №9 при нажатии на любую из символьных клавиш.

Задача 2.4.Опишите алгоритм работы программы обработки прерывания №9 при нажатии на любую из управляющих клавиш.

Задача 2.5.(*) Напишите программу для определения SCAN-кодов символьных клавиш и ASCII-кодов соответствующих им символов (используйте средства прямого доступа к порту №60h и буферу клавиатуры).

ВИДЕОСИСТЕМА ПК

Наши рекомендации