Реальная необходимость в непосредственной работе с клавиатурой возникает в том случае, если вы создаете программу, которая переводит процессор из реального режима в защищенный, а затем выполняет в защищенном режиме всю дальнейшую работу. Переход в защищенный режим приводит к тому, что функции BIOS, рассчитанные на реальный режим, становятся непригодными для использования.
Для управления работой клавиатуры в машинах типа IBM AT и PS/2 использовался микроконтроллер Intel 8042. Кроме клавиатуры, этот контроллер управлял также координатным устройством, в качестве которого обычно использовалась мышь типа PS/2. С целью обеспечения совместимости нового аппаратного обеспечения со старыми программами все современные наборы микросхем, предназначенные для изготовления системных плат (так называемые чипсеты), вынужденно повторяют в своей структуре особенности контроллера i8042 [57, 69, 70, 79, 98].
Писать программы для клавиатурного контроллера i8042 и встроенного микропроцессора клавиатуры нет необходимости и возможности, да и бесполезно, поскольку соответствующие программы уже «намертво» записаны в ПЗУ контроллеров. Поэтому клавиатурный контроллер на системной плате и микропроцессор клавиатуры могут выполнять только те операции, которые заложены в них разработчиками аппаратуры и внесены в соответствующие наборы команд. Самопроверка контроллера и программирование основных
параметров его работы, а также самотестирование и программирование параметров клавиатуры (и мыши PS/2) производятся при включении компьютера и могут быть изменены с помощью прерываний BIOS, пока процессор еще не переведен из реального режима в защищенный. В защищенном режиме необходимо выполнять только два типа операций: считывание кодов нажимаемых клавиш и зажигание/гашение светодиодов на клавиатуре. Этим операциям уделяется основное внимание, а бесполезная на практике часть информации о программировании контроллера будет опущена (при необходимости дополнительные сведения можно найти в литературе [6, 7, 14, 30]). В данной главе мы рассмотрим только функционирование клавиатурного контроллера и клавиатуры (управление мышью PS/2 будет рассматриваться в главе 5 «Работа с мышью»).
Управление работой контроллера и обмен данными с мышью и клавиатурой осуществляются при помощи трех регистров: регистра состояния, регистра команд и регистра данных. Кроме того, при поступлении информации от клавиатуры контроллер i8042 вырабатывает прерывание IRQ.1, а при приеме данных от мыши — IRQ12. Интерфейсы клавиатуры и мыши аналогичны, наборы команд управления также имеют некоторое сходство. Упрощенная схема подключения к компьютеру клавиатуры и мыши типа PS/2 показана на рис. 1.5.
Регистр состояния доступен только для считывания через порт 64h. Формат регистра показан на рис. 1.6. Значение разрядов регистра следующее:
• бит 0 — признак наличия данных в выходном буфере (0 — буфер пуст, 1 — буфер заполнен);
• бит 1 — признак наличия данных во входном буфере (0 — буфер пуст, 1 — буфер заполнен);
• бит 2 — признак типа последнего общесистемного сброса (0 — сброс по включении питания, 1 — программный сброс);
• бит 3 — признак записи команды (0 — последняя операция записи являлась операцией записи данных, 1 — записи команды);
• бит 4 — состояние «замка» клавиатуры (0 — клавиатура блокирована, 1 — не блокирована);
• бит 5 — признак ошибки тайм-аута передачи в АТ-режиме (0 — нормальное завершение передачи, 1 — произошла ошибка); признак наличия данных в выходном буфере мыши в PS/2-режиме (0 — буфер пуст, 1 — буфер заполнен);
• бит 6 — признак ошибки тайм-аута приема в АТ-режиме (0 — нормальное завершение приема, 1 — произошла ошибка); общий признак ошибки тайм-аута при приеме или передаче данных в PS/2-режиме (0 — нормальное завершение операции, 1 — произошла ошибка);
• бит 7 — признак возникновения ошибки паритета при приеме или передаче данных (0 — нет ошибки, 1 — обнаружена ошибка по четности).
Рис. 1.5. Упрощенная схема подключения клавиатуры и мыши типа PS/2
к компьютеру
Рис. 1.6. Формат регистра состояния контроллера клавиатуры
Рис. 1.7. Формат регистра команд контроллера клавиатуры
Регистр команд доступен для записи через порт 64h. Формат регистра показан на рис. 1.7. Разряды регистра имеют следующее назначение:
• бит 0 — управление выдачей сигнала прерывания по готовности данных в выходном буфере клавиатуры (0 — генерация прерывания запрещена, 1 — разрешена);
• бит 1 — управление выдачей сигнала прерывания по готовности данных в выходном буфере мыши (0 — генерация прерывания запрещена, 1 — разрешена);
• бит 2 — установка признака системного сброса (значение, записанное в этот разряд, переносится в разряд 2 регистра состояния);
• бит 3 — управление функцией блокировки клавиатуры (0 — функция блокировки разрешена, 1 — функция запрещена и блокировка игнорируется);
• бит 4 — управление интерфейсом клавиатуры (0 — обмен данными с клавиатурой разрешен, 1 — запрещен);
• бит 5 — признак типа протокола передачи данных в АТ-режиме (О — протокол IBM); управление интерфейсом мыши в PS/2-ре- жиме (0 — обмен данными с мышью разрешен, 1 — запрещен);
• бит 6 — преобразование скан-кодов в PC-совместимые (0 — выключено, 1 — включено); по умолчанию имеет значение 1, то есть скан-коды преобразуются в РС-совместимые;
• бит 7 — не используется (зарезервирован).
Коды команды управления приведены в табл. 1.8. Некоторые из команд двухбайтные, то есть имеют данные: первый байт (код команды) в этом случае записывается в регистр команд, а следующий — в регистр данных. Двухбайтными являются команды 60h, Dlh-D4h.
Клавиатурный контроллер системной платы может работать в двух различных режимах: в АТ-режиме он может управлять только клавиатурой, в PS/2-режиме — клавиатурой и мышью. Регистр команд обеспечивает грубую установку режима работы клавиатуры и мыши. Кроме того, режимами работы также можно управлять, посылая в регистр определенные кодовые комбинации.
Регистр данных доступен для записи и считывания через порт 60h. В режиме считывания он служит для приема информации от клавиатуры и мыши. В режиме записи регистр данных служит для передачи команд клавиатуре, координатному устройству (мыши PS/2-типа) и клавиатурному контроллеру системной платы i8042. Какого-либо особого формата данный регистр не имеет.
Таблица 1.8. Команды управления контроллером клавиатуры и мыши
|
Код |
Назначение команды |
|
20h |
Чтение содержимого регистра команд |
|
60h |
Запись командного байта в регистр команд |
|
A1h |
Чтение номера версии контроллера |
|
A4h |
Проверка «пароля» (признака подключения клавиатуры). |
|
|
При успешном выполнении команды выдается строка «F1» |
|
A7h |
Запретить работу с мышью (команда выполняется только в режиме |
|
|
PS/2, в АТ-режиме игнорируется) |
|
A8h |
Разрешить работу с мышью (команда выполняется только |
|
|
в режиме PS/2, в АТ-режиме игнорируется) |
|
A9h |
Тест интерфейса мыши (при успешном выполнении команды |
|
|
генерируется значение 00h) |
|
AAh |
Самотестирование контроллера (при успешном выполнении |
|
|
команды генерируется значение 55h) |
|
ABh |
Тест интерфейса клавиатуры (при успешном выполнении команды |
|
|
генерируется значение 00h) |
|
ADh |
Запретить работу с клавиатурой |
|
AEh |
Разрешить работу с клавиатурой |
|
AFh |
Выдать номер версии |
|
COh |
Чтение байта состояния входного порта (порта № 1) |
|
DOh |
Чтение байта состояния выходного порта (порта № 2) |
|
D1h |
Запись байта в выходной порт (порт № 2) |
|
D2h |
Запись байта в выходной буфер клавиатуры |
|
D3h |
Запись байта в выходной буфер мыши |
|
D4h |
Передать мыши байт данных |
Клавиатура может работать в трех различных режимах, которые отличаются друг от друга наборами скан-кодов, выдаваемых клавиатурой. Набор № 1 предназначен для компьютеров типа IBM «PS/2 30», набор № 2 – для «PC/AT», «PS/2 50» и «PS/2 60», набор № 3 — для «PS/2 80». Для переключения режимов работы используется команда FOh. Однако программисты никогда не сталкиваются непосредственно с наборами кодов, выдаваемыми клавиатурой, а имеют дело с преобразованным набором, выдаваемым клавиатурным процессором системной платы (так что переключение режима — обычно не только бесполезная, но даже вредная операция). Если потребуется использование типовой компьютерной клавиатуры в каком-либо самодельном устройстве, то стандартные наборы скан-кодов можно посмотреть в специальной литературе, например в [6] или [57].
При включении питания клавиатура устанавливается в режим № 2, причем для всех клавиш разрешена посылка кодов нажатия и отпускания, а также разрешен автоповтор. Самотестирование после включения выполняется в следующем порядке:
• включаются все индикаторы;
• тестируется встроенный микроконтроллер клавиатуры;
• тестируется оперативная память клавиатуры;
• все индикаторы выключаются;
• клавиатура выдает компьютеру результат самотестирования. Когда разрешен опрос клавиш, клавиатура передает компьютеру скан-коды, сообщающие об изменении их состояния (под изменением состояния подразумевается нажатие, длительное удержание или отпускание). Кроме того, возможна посылка следующих специализированных кодов в ответ на команду или при возникновении неисправностей:
• 00h — возникла ошибка переполнения (в режиме № 2 или № 3);
• AAh — самотестирование прошло успешно;
• последовательность ABh, B3h — идентификатор клавиатуры;
• EEh — ответ на эхо-команду EEh;
• FAh — подтверждение приема информации (команда АСК);
• FCh — в процессе самотестирования обнаружена неисправность;
• FEh — запрос на повторную передачу команды со стороны компьютера, выдается в случае возникновения ошибки передачи;
• FFh — возникла ошибка переполнения (в режиме № 1).
Список команд управления встроенным процессором клавиатуры приведен в табл. 1.9.
Таблица 1.9. Команды управления встроенным процессором клавиатуры
|
Код |
Назначение команды |
|
EDh |
Установить состояние индикаторов (светодиодов) |
|
EEh |
Эхо-диагностика |
|
FOh |
Изменить режим работы (набор скан-кодов) |
|
F2h |
Выдать идентификационную последовательность кодов |
|
F3h |
Установить параметры режима автоповтора |
|
F4h |
Разрешить передачу данных |
|
F5h |
Установить значение параметров работы, используемое |
|
|
по умолчанию, и запретить опрос клавиш |
|
F6h |
Установить значение параметров работы, используемое по умолчанию |
|
F7h |
Разрешить режим автоповтора для всех клавиш |
|
F8h |
Разрешить для всех клавиш посылку кодов нажатия и отпускания |
|
F9h |
Разрешить для всех клавиш посылку только кодов нажатия |
|
FAh |
Разрешить для всех клавиш режим автоповтора, посылку кодов |
|
|
нажатия и отпускания |
|
FBh |
Разрешить режим автоповтора заданной клавиши |
|
FCh |
Разрешить для заданной клавиши посылку только кода нажатия |
|
FDh |
Разрешить для заданной клавиши посылку кодов нажатия и отпускания |
|
FEh |
Повторить передачу пакета данных |
|
FFh |
Произвести сброс |
Рассмотрим приведенные в таблице команды более подробно.
Команда EDh предназначена для включения и выключения индикаторов состояния клавиатуры (светодиодов Num Lock, Caps Lock и Scroll Lock). Команда двухбайтная — байт данных, следующий за кодом команды, содержит информацию, управляющую включением и выключением светодиодов. Формат байта данных следующий:
• бит 0 — состояние индикатора Scroll Lock (0 — выключен, 1 — включен);
• бит 1 — состояние индикатора Num Lock (0 — выключен, 1 — включен);
• бит 2 — состояние индикатора Caps Lock (0 — выключен, 1 — включен);
• биты 3-7 не используются.
На команду управления индикаторами клавиатура реагирует следующим образом:
• посылает байт АСК в компьютер;
• останавливает опрос клавиш;
• принимает от компьютера байт данных, определяющий новое состояние индикаторов;
• посылает байт АСК в компьютер;
• устанавливает индикаторы в заданное состояние.
Команда EEh предназначена для эхо-диагностики (в ответ микропроцессор клавиатуры также выдает код EEh). Обычно команда используется при возникновении ошибок в работе клавиатуры. Посылка команды EEh после выполнения сброса клавиатуры позволяет определить, восстановился ли нормальный режим функционирования. Неправильный ответ на эхо-команду означает, что процессор клавиатуры «зациклился» и привести систему в нормальное состояние можно только отключением питания. Реакция клавиатуры на команду EEh следующая:
• компьютеру выдается код EEh;
• продолжается работа в том режиме, который был установлен до поступления команды.
Команда FOh позволяет установить один из трех наборов скан-кодов, используемых для передачи данных от клавиатуры к клавиатурному процессору материнской платы. Команда двухбайтная — байт данных должен следовать за байтом команды и содержать номер устанавливаемого набора (1,2 или 3). Клавиатура реагирует на команду следующим образом:
• посылает байт АСК в компьютер;
• очищает выходной буфер;
• принимает байт данных, содержащий номер устанавливаемого режима;
• устанавливает новый режим.
Команда F2h служит для идентификации типа устройства, подключенного к клавиатурному разъему компьютера, то есть для проверки того, что в разъем включена именно клавиатура, а не присоединено по ошибке какое-либо другое устройство вроде мыши или джойстика. Реакция клавиатуры на команду идентификации следующая:
• клавиатура посылает компьютеру байт АСК;
• приостанавливается опрос клавиш;
• клавиатура посылает компьютеру код ABh, затем — код 83h;
• опрос клавиш возобновляется.
Команда F3h позволяет установить значение частоты и задержки автоповтора. Команда является двухбайтной — байт данных следует за кодом команды и имеет следующую структуру:
• биты 0-4 — код частоты автоповтора (см. табл. 1.5);
• биты 5-6 — код задержки автоповтора (см. табл. 1.4);
• бит 7 — не используется (всегда должен иметь значение 0).
Клавиатура реагирует на команду установки параметров автоповтора следующим образом:
• посылает байт АСК в компьютер;
• останавливает опрос клавиш;
• принимает от компьютера байт данных, определяющий новое значение параметров автоповтора;
• посылает байт АСК в компьютер;
• устанавливает заданные параметры автоповтора.
Команда F4h разрешает микропроцессору клавиатуры возобновить опрос клавиш и передачу данных компьютеру. Реакция клавиатуры на команду F4h следующая:
• клавиатура посылает байт АСК в компьютер;
• производится очистка выходного буфера;
• если какая-либо клавиша работала в режиме автоповтора, то автоповтор прекращается;
• возобновляется опрос клавиш.
Команда F5h устанавливает значения параметров клавиатуры, принятые по умолчанию, и останавливает сканирование (опрос клавиш и передачу данных об изменении их состояния компьютеру). Микропроцессор клавиатуры реагирует на команду F5h следующим образом:
• посылает байт АСК в компьютер;
• стирает выходной буфер;
• разрешает для всех клавиш (кроме Pause) автоповтор и посылку кодов нажатия и отпускания;
• устанавливает используемое по умолчанию значение параметров автоповтора;
• прекращает автоповтор, если какая-то клавиша работала в режиме автоповтора;
• прекращает опрос клавиш;
• переходит в режим ожидания дальнейших инструкций. Команда F6h устанавливает значения параметров клавиатуры, принятые по умолчанию. Клавиатура реагирует следующим образом:
• посылает байт АСК в компьютер;
• стирает выходной буфер;
• разрешает для всех клавиш (кроме Pause) автоповтор и посылку кодов нажатия и отпускания;
• устанавливает используемое по умолчанию значение параметров автоповтора.
Команды F7h—FAh определяют тип реакции клавиатурного процессора на нажатие, удержание и отпускание клавиш. Команды воздействуют сразу на все клавиши клавиатуры: команда F7h включает режим автоповтора, команда F8h разрешает посылку кодов нажатия и отпускания, команда F9h — только кодов нажатия, а команда FAh включает автоповтор и разрешает посылку кодов нажатия и отпускания. Реакция клавиатуры на любую из этих команд следующая:
• клавиатура посылает байт АСК в компьютер;
• очищает выходной буфер;
• устанавливает заданный тип реакции на нажатие, удержание и отпускание клавиш.
Команды FBh-FDh определяют тип реакции клавиатурного процессора на нажатие, удержание и отпускание конкретной, указанной в команде клавиши. Эти команды двухбайтовые — второй байт задает идентификатор клавиши, для которой производится установка индивидуального режима. Команда FBh включает режим автоповтора, команда FCh разрешает посылку кодов нажатия и отпускания, команда FDh — только кодов нажатия. Данные команды выполняются только в том случае, если клавиатура функционирует в режиме № 3. Клавиатура реагирует на любую из них следующим образом:
• посылает байт АСК в компьютер;
• очищает выходной буфер;
• ожидает поступления кода-идентификатора клавиши;
• устанавливает для заданной клавиши заданный тип реакции на нажатие, удержание и отпускание.
Режим работы клавиатуры устанавливается при запуске компьютера процедурами BIOS, и после этого изменять его обычно нет необходимости. Единственная команда, которую драйвер периодически посылает клавиатуре, — команда переключения светодиодов EDh. Данная команда является ответной реакцией драйвера на нажатие клавиш Num Lock, Caps Lock и Scroll Lock.
Как уже отмечалось выше, набор скан-кодов, которые выдает клавиатурный процессор системной платы, отличается и от набора скан-кодов, которые используют процедуры BIOS. На рис. 1.8 показаны коды, присвоенные клавишам основной и функциональной групп, на рис. 1.9 — коды дополнительной клавиатуры, а на рис. 1.10 — коды цифровой клавиатуры.
Рис. 1.8. Скан-коды клавиш основной и функциональной клавиатур

Рис. 1.9. Скан-коды клавиш дополнительной клавиатуры

Рис. 1.10. Скан-коды клавиш цифровой клавиатуры
Нажатие клавиши приводит к передаче от клавиатуры к компьютеру одного символа или последовательности символов (от двух до шести). При нажатии обычных клавиш (алфавитно-цифровых или функциональных) передается только один байт, содержащий скан- код. Последовательности генерируются для клавиш, которые отсутствовали в 84-кнопочной клавиатуре XT-типа, и состоят из кодовых пар, причем каждая пара начинается с кода EOh, а во втором байте передается скан-код. Последовательность из четырех байт (двух пар) передается в том случае, если нажата дополнительная клавиша, заменяющая собой нажатие определенной последовательности обычных клавиш. Специфическая последовательность из шести байт генерируется только в одном случае — при нажатии клавиши Pause.
При отпускании клавиши клавиатура также посылает в компьютер скан-код, но старший (знаковый) разряд кода при этом устанавливается в единицу. Отпускание клавиши, выдающей пару кодов, можно отличить от нажатия по второму символу пары (первым кодом в паре по прежнему является EOh, а у скан-кода при отпускании будет установлен старший разряд). При отпускании дополнительных клавиш генерируются две пары кодов, но порядок этих пар является обратным тому, который генерируется при их нажатии, и установлены старшие разряды скан-кодов. При отпускании клавиши Pause клавиатура никакой информации в компьютер не передает. Например, при нажатии клавиши Пробел вырабатывается код 39h, а при отпускании — код B9h. При нажатии клавиши 1 на основной клавиатуре вырабатывается код 02h, а при отпускании — код 82h; нажатие клавиши 1 на цифровой клавиатуре порождает код 4Fh, а отпускание — код CFh. При нажатии правой клавиши Ctrl вырабатывается последовательность ЕО, lDh, а при отпускании — последовательность EOh, 9Dh. Нажатие Insert порождает последовательность кодов EOh, 2Ah, EOh, 52h, а отпускание — последовательность EOh, D2h, EOh, AAh. Нажатие клавиши Pause приводит к выдаче последовательности Elh, lDh, 45h, Elh, 9Dh, C5h, а при отпускании данной клавиши никаких кодов не вырабатывается вообще.
Для поддержки расширенного интерфейса управления конфигурацией и питанием (Advanced Configuration and Power Interface, сокращенно ACPI) на клавиатуру были добавлены три клавши [71]:
• Power (Выключить питание) — вырабатывает последовательность EOh, 5Eh;
• Sleep (Переключить систему в спящий режим) — вырабатывает последовательность EOh, 5Fh;
• Wake (Разбудить систему) — вырабатывает последовательность EOh, 63h.
Появились в продаже также так называемые «Мультимедийные клавиатуры» с целой группой дополнительных клавиш:
• Next Track — вырабатывает последовательность EOh, 19h;
• Previous Track — вырабатывает последовательность EOh, 10h;
• Stop — вырабатывает последовательность EOh, 24h;
• Play/Pause — вырабатывает последовательность EOh, 22h;
• Mute — вырабатывает последовательность EOh, 20h;
• Volume Up — вырабатывает последовательность EOh, 30h;
• Volume Down — вырабатывает последовательность EOh, 2Eh;
• Media Select — вырабатывает последовательность EOh, 6Dh;
• E-Mail — вырабатывает последовательность EOh, 6Ch;
• Calculator — вырабатывает последовательность EOh, 21h;
• My Computer — вырабатывает последовательность EOh, 6Bh;
• WWW Search — вырабатывает последовательность EOh, 65h;
• WWW Home — вырабатывает последовательность EOh, 32h;
• WWW Back — вырабатывает последовательность EOh, 6Ah;
• WWW Forward — вырабатывает последовательность EOh, 69h;
• WWW Stop — вырабатывает последовательность EOh, 68h;
• WWW Refresh — вырабатывает последовательность EOh, 67h;
• WWW Favorites — вырабатывает последовательность EOh, 66h.
ПРИМЕЧАНИЕ
Местоположение дополнительных клавиш на клавиатуре не стандартизировано. Обычно мультимедийные клавиши размещаются в один ряд над функциональными клавишами, а клавиши ACPI находятся между клавишами дополнительной клавиатуры.
Примеры программ, работающих непосредственно с контроллером клавиатуры, приведены в листингах 1.6 и 1.7. Программа KeyboardTest из листинга 1.6 предназначена для отображения на экран потока кодов, поступающих с клавиатуры. Она позволяет наблюдать реакцию клавиатуры на нажатие, удержание и отпускание клавиш различных типов. Процедура обработки клавиатурного прерывания IRQl Keyboardlnterrupt отображает принятый от клавиатуры код на экран в шестнадцатеричном представлении, а затем производит подготовку к выводу следующего кода (изменяет.значение текущих экранных координат ScreenCol umn и ScreenString). Для установки вектора прерывания на эту процедуру служит подпрограмма SetKeyboardlnterrupt, а для восстановления старого вектора прерывания после завершения работы основной программы используется подпрограмма RestoreOldKeyboardlnterrupt.
Листинг 1.6. Отображение потока данных от клавиатуры в шестнадцатеричных кодах
IDEAL
Р386
LOCALS
MODEL MEDIUM
: Подключить файл мнемонических обозначений
; кодов управляющих клавиш и цветовых кодов
Include "1 istl_03.inc"
; Подключить файл макросов
Include "listl__04.inc"
SEGMENT sseg para stack ‘STACK’
DB 400h DUP(?)
ENDS
DATASEG
; Счетчик операций нажатия/отпускания клавиш PressCounter DW ?
; Область сохранения старого вектора прерывания клавиатуры OldKeyboardlnterruptOffset DW ? OldKeyboardlnterruptSegment DW ? : Текстовые сообщения
Листинг 1.6 (продолжение)
Text
DB LIGHTGREEN.O.19
DB "Непосредственный прием данных с клавиатуры",О DB’YELLOW,4,0,"Отображение потока данных "
DB "в шестнадцатеричных кодах:",О
DB LIGHTBLUE.24,29,"Нажмите любую клавишу",О
ENDS CODESEG
• А А1 А А А А АЛ’^^’А’А А "А" А1 А А’ А А"А А1 А* А1 А* А1 А* Л* А1 А*
;* Основной модуль программы *
• ‘А’ А А* А А А1 А А А А А А А’А Аг А А А"А’ А А* А А А А А1 А А А1
PROC KeyboardTest
mov AX.DGROUP
mov DS.AX
mov [CS:Mai nDataSeg],AX
; Установить текстовый режим и очистить экран
mov АХ.З int 10h
: Скрыть курсор – убрать за нижнюю границу экрана
mov [ScreenStri ng],25
mov [ScreenColumn],0 call SetCursorPosition : Вывести текстовые сообщения на экран
MShowColorText 3,Text : Установить белый цвет символов и черный фон
mov [TextColorAndBackground],WHITE
; Установить начальную позицию для вывода кодов : в нулевой колонке пятой строки
mov [ScreenString],5
mov [ScreenColumn],О
; Инициализировать счетчик операций : нажатия/отпускания клавиш
mov [PressCounter],О : Установить новый обработчик прерывания call SetKeyboardlnterrupt
: Ожидать, пока не будет произведено 200
; операций нажатия/отпускания
@@Next: cmp [PressCounter],200 jb
@@Next
; Восстановить исходный обработчик прерывания
call RestoreOldKeyboardlnterrupt : Переустановить текстовый режим и очистить экран
mov АХ.З int 10h : Передать управление DOS
mov AH,4Ch int 21h
ENDP KeyboardTest
;* НОВЫЙ ОБРАБОТЧИК ПРЕРЫВАНИЯ ОТ КЛАВИАТУРЫ *
• А’А’Л’Л’Л’АгАг’А^А А А А А А А1 А"А А"А’ А1 А" А АгА’Аг АгА А* А А А’ А"ААгА1 Аг*АгАг АпА
ргос Keyboardlnterrupt far pus ha
push OS
mov AX,[CS:MainDataSeg]
mov DS.AX
; Получить скан-код
in AL,60h
; Разрешить прерывания с более низким приоритетом push АХ
mov AL,20h :команда EOI out 20h,AL pop • AX
stiразрешить прерывания
; Отобразить на экране монитора принятый от клавиатуры : код в шестнадцатеричном представлении
; Отобразить принятый байт саТ1 ShowHexByte
; Перевести текущую позицию на 2 символа влево
; (подготовка для вывода следующего кода)
add [ScreenColumn],2
; Проверить пересечение правой границы экрана cmp [ScreenColumn],80 jb
@@EndShowCode
; Если достигнута правая граница
; экрана – перейти на следующую строку sub [ScreenColumn],ВО
inc [ScreenString] PPEndShowCode:
; Завершение обработки прерывания
; Увеличить значение счетчика нажатий/отпусканий
inc [PressCounter]
pop DS
рора
iret
endp Keyboardlnterrupt
;* УСТАНОВИТЬ НОВЫЙ ОБРАБОТЧИК ПРЕРЫВАНИЯ КЛАВИАТУРЫ *
« А А А А" А А А’ ‘А’ А А’А’А^А’А Аг А* А А’ А1 А А1 А1 М А’ А’Аг А* А1 Ат А’ А"А А А1 А А" А"А А А ‘А А’ А А’ А’ А"А А1 А А’ А* А А’
PROC SetKeyboardInterrupt NEAR pus ha
push ES
mov AX.O
mov ES.AX
Листинг 1.6 (продолжение)
; Запомнить прежний вектор обработчика
; прерывания клавиатуры
mov АХ,[ES:9*4]
mov [01dKeyboardlnterruptOffset],АХ
mov AX. [ES: 9*4+2]
mov [OldKeyboardlnterruptSegment],AX : Установка вектора прерывания на обработчик клавиатуры cli;запретить прерывания
mov АХ,offset Keyboardlnterrupt
mov [ES:9*4],AX
mov AX.CS
mov [ES:9*4+2].AX sti-.разрешить прерывания
pop ES popa ret
ENDP SetKeyboardlnterrupt
;* ВОССТАНОВИТЬ ИСХОДНЫЙ ВЕКТОР ПРЕРЫВАНИЯ *
************************************ АЛЛ****
PROC RestoreddKeyboardlnterrupt NEAR pusha
; Настроить регистр ES на таблицу векторов прерываний push ES
mov АХ.О
mov ES.AX
; Восстановить прежний вектор обработчика прерывания cli
mov АХ.[OldKeyboardlnterruptOffset]
mov [ES:9*4],AX
mov AX,[OldKeyboardlnterruptSegment]
mov [ES:9*4+2].AX
sti
pop ES
popa
ret
ENDP RestoreddKeyboardlnterrupt ENDS
: Подключить процедуры вывода данных на экран
Include "listl_02.inc"
END
Программа KeyboardDri ver из листинга 1.7 демонстрирует выполнение следующих типовых операций над данными, поступающими от клавиатурного контроллера системной платы:
• преобразование скан-кодов в ASCII-коды;
• обработка управляющих клавиш;
• управление светодиодами клавиатуры.
Кроме процедур общего назначения, в программе KeyboardDri ver используются следующие подпрограммы:
• процедура Keyboardlnterrupt принимает данные от клавиатуры, обрабатывает их и при необходимости запоминает введенный символ в выделенной для него ячейке или переключает состояние светодиодов на клавиатуре;
• процедура SetKeyboardlnterrupt служит для установки вектора прерывания от клавиатуры на подпрограмму’Keyboardlnterrupt;
• процедура RestoreOldKeyboardlnterrupt служит для восстановления прежнего вектора прерывания после завершения работы программы;
• процедура Wait8042BufferEmpty выполняет цикл ожидания освобождения буфера контроллера клавиатуры.
Листинг 1.7. Упрощенный вариант драйвера клавиатуры
IDEAL
Р386
LOCALS
MODEL MEDIUM
; Подключить файл мнемонических обозначений
; кодов управляющих клавиш и цветовых кодов
Include "listl_03.inc"
; Подключить файл макросов
Include "listl_04.inc"
SEGMENT sseg para stack ‘STACK’
DB 400h DUP(?)
ENDS
DATASEG
; Счетчик операций нажатия/отпускания клавиш PressCounter DW ?
; Область сохранения старого вектора
; прерывания клавиатуры OldKeyboardlnterruptOffset DW ? OldKeyboardlnterruptSegment DW ?
; Байт состояния клавиатуры (бит 0 – Scroll Lock,
; бит 1 • NumLock, бит 2 • CapsLock, бит 3 • левый
Листинг 1.7 (продолжение)
; Shift, бит 4 – правый Shift) KeyboardStatus
DB О
: Байт состояния светодиодов (бит 0 – ScrollLock,
; бит 1 – NumLock, бит 2 – CapsLock) LEDStatus
DB О
; Признак ввода очередного символа CharlnputFlag
DB О
; ASCII-код введенного символа ASCIICode
DB О
; Текстовые сообщения Text
DB LIGHTGREEN.0,21
DB "Упрощенный вариант драйвера клавиатуры",О
DB YELLOW,10.О
DB "Отображение потока данных в ASCII-кодах:",0
DB LI6HT6REY,24,29,"Нажмите любую клавишу",0 : Перекодировочные таблицы (для алфавитно-цифровой
; клавиатуры) label RusNorm byte
DB 0 . 27. ‘Г, ‘г’. ’3′. ’4′, ’5′, ’6′
DB v/ev^/ov-v-1. 8 , 9
DB ‘й’.'ц’,'у’,'к’.'е’,'н’,'г’
DB ‘ш’, ‘щ’. ‘з’, ‘х’, Ч’, 13. О
DB ‘ф".’ы’,'в’,'а’,'п’.'р’,'о’
DB ‘л’.'д’.'ж’,1э’,'ё’, 0 ,1 \’
DB ‘я’.'ч’.'с’.'м’.'и’.'т’.'ь’
DB ‘б’,'ю’.\\ 0 ,’*', 0 ,’ ‘ label RusNormShift byte
DB 0 . 27,’!',"",’Г.’;',’Г ,’:’
DB ^’.'?Vr,’)',’_’.’+', 8 , 9
DB ‘Й’.'Ц’.'У’.'К’.'Е’.'Н’.Т’
DB ‘Ш’.'Щ’.'З’.'Х’.'Ъ’. 13, 0
DB ‘Ф’.'Ы’.'В’.'А’.'П’.'Р’.'О’
DB ‘Л’.'Д’.'Г.’Э’.'Ё’, 0 ,’/’
DB ‘Я’.'Ч’.'С’.'М’.'И’.'Т’.'Ь’
DB ‘Б’.'Ю’,',’, 0 ,’*', 0 .’ ‘ label RusCaps byte
DB 0 , 27,’1′.’2′,’3′,’4′.’5′.’6′
DB ’7′,’8′.’9′,’0′.•-’,'=’. 8 . 9
DB ‘Й’/Ц’.'У’.'К’.'Е’.'Н’.'Г’
DB ‘ИГ.’Щ’.'З’.'Х’.'Ъ’, 13, 0
DB ‘Ф’.'Ы’.'В’.'А’.'П’.'Р’.'О’
DB ‘Л’.'Д’.'Г.’Э’.'Ё’, 0 ,’\’
DB ‘Я’.'Ч’.'С’.'М’.'И’.'Т’.'Ь’
DB ‘Б’.'Ю’,’.’. 0 ,’*', 0 ,’ ‘ label RusCapsShift byte
DB 0 . 27,’!’."", ‘Ife’,';’, 4′,’:’
DB ‘?’.•*•.’(‘.’)',’_’.’+', В , 9
DB ‘й’.'ц’.'у’,'к’,'e’,'н’.'г’
DB ‘ш’, ‘щ’, ‘з’. ‘х’ Л’. 13. О
DB’ф’,'ы’,'в’,'а’,'п’,'р’,'о’
DB’л’,'д’, V,"э’, ‘ё’, 0 ,’/’
DB’я’,'ч’,'с’,V,’и’,'т’,'ь’
DB’б’, v.’,’. О ,’*•, 0 1 ENDS
C0DESE6
• А А1 ‘А’ А А1 А А А’ А1 А1 А* А’ ‘А1 А1 ‘А’ А1 А Л А ‘А А" А А А А А AAA
;* Основной модуль программы *
PROC KeyboardDriver
mov AX.D6R0UP
mov DS.AX
mov [CS:MainDataSeg],AX
; Установить текстовый решим м очмстить экран
mov АХ.З int 10h
; Вывести текстовые сообщения на экран
MShowColorText 3,Text
; Инициализировать счетчик операций
; нажатия/отпускания клавиш
mov [PressCounter],О
; Установить новый обработчик прерывания
call SetKeyboardlnterrupt : Установить курсор в начало строки
mov [ScreenString],12
mov [ScreenColumn],0 call SetCursorPosition
; Настроить ES:DI на видеопамять
mov AX,0B800h ;текстовый видеосегмент
mov ES.AX
mov AH,WHITE ;белый цвет, черный фон
; Выполнять вывод символов в двенадцатой строке
mov DI,12*160
; Ввести и отобразить на экране ВО символов
@@NextChar:
cmp [CharInputFlag],0 ;Введен символ?
je
@@NextChar
: Сбросить флаг ввода символа
mov [CharInputFlag],0
; Отобразмть символ
mov AL,[ASCIICode]
stosw
; Передвинуть курсор в следующую позицию
inc [ScreenColumn]
call SetCursorPosition
; Увеличить счетчик
inc [PressCounter]
; Проверить условие завершения цикла
Листинг 1.7 (продолжение)
cmp [PressCounter],80 jb
@@NextChar
; Восстановить исходный обработчик прерывания
call RestoreOldKeyboardlnterrupt
; Переустановить текстовый решим и очистить экран
mov АХ.З int 10h
; Передать управление DOS
mov AH,4Ch int 21h ENDP KeyboardDriver
;* НОВЫЙ ОБРАБОТЧИК ПРЕРЫВАНИЯ DT КЛАВИАТУРЫ *
• A ‘A’A A A^’A^^A A A’A'AiA’^IA’A'A’A A A A A^^A A^^A A A A AA АЛ A’lfr
proc Keyboardlnterrupt far .•Сохранить регистры pusha
push DS
mov AX.[CS:Mai nDat aSeg]
mov DS.AX
; Получить скан-код
in AL,60h
разрешить прерывания
push AXсохранить скан-код
mov AL,20h ;послать команду EDI
out 20h,AL ;в ведущий контроллер
pop AXвосстановить скан-код
sti
; Игнорировать код подтверждения команды АСК
cmp AL.OFAh ;код подтверждения команды?
je
@@End
; Обработать Shift
cmp AL,2Ah ;левый Shift нажат
je
@@LeftShi ftON cmp AL.OAAh ;левый Shift отпущен
je
@@[_eftShi ftOFF cmp AL,36h ;правый Shift нажат
je
@@RightShiftON cmp AL,0B6h ;правый Shift отпущен
je
@@RightShiftOFF Проверить нажатие клавиш статуса
cmp AL,3Ah ;нажатие клавиши CapsLock?
je
@@CapsLockLED_ON cmp AL,45h ;нажатие клавити NumLock?
je
@@NumLockLED_DN cmp AL,46h :нажатие клавиши ScrollLock?
je
@@Scrol 1 LockLED_0N
; Обработать алфавитно-цифровые клавиши cmp AL,39h ja §PEnd
; Использовать скан-код как индекс : элемента в массиве перекодировки хог ВХ.ВХ
mov BL.AL
; Выбрать массив перекодировки
test [KeyboardStatus],100b ;CapsLock активен?
jnz
@@CapsON
test [KeyboardStatus],11000b ;Shi ft нажат? jnz GxaShiftONl
add BX.offset RusNorm
jmp short
@@SaveChar 0aShiftONl:
add BX,offset RusNormShift
jmp short
@@SaveChar
@@Caps0N:
test [KeyboardStatus],11000b ;Shi ft нажат? jnz
@@Shi ft0N2
add BX,offset RusCaps
jmp short
@@SaveChar
@@Shift0N2:
add BX.offset RusCapsShift
@@SaveChar:
; Сохранить ASCII-код символа и установить флаг приеиа
mov AL,[BX]
cmp AL.32 ;это алфавитно-цифровой символ?
jb §PEnd
mov [ASCIICode],AL
mov [CharlnputFlag], 1
jmp short
@@End
; Установить признак Shift MteftShiftON:
or [KeyboardStatus].1000b
jmp short
@@End
@@LeftShift0FF:
and [KeyboardStatus],11110111b
jmp short
@@End
@@RightShift0N:
or [KeyboardStatus],10000b
jmp short
@@End
@@RightShift0FF:
and [KeyboardStatus],11101111b
jmp short
@@End
Листинг 1.7 (продолжение)
; При нажатии клавиши статуса зажечь или погасить
; соответствующий светодиод
@@CapsLockLED_DN:
xor [LEDStatus],100b
jmp short
@@SetKeyboardLED
@@NumLockLED_ON:
xor [LEDStatus],10b
jmp short
@@setKeyboardLED
@@Scrol1LockLED_ON:
xor [LEDStatus], 1 MSetKeyboardLED:
; Сбросить незначащие разряды and [LEDStatus],111b
; Скопировать LEDStatus в KeyboardStatus and [KeyboardStatus],11111000b
mov AL,[LEDStatus] or [KeyboardStatus],AL
; Переустановить состояние светодиодов на клавиатуре call Wa i t8042BufferEmpty
; Послать команду установки светодиодов
mov AL.OEDh out 60h,AL call Wait8042BufferEmpty
; Передать байт состояния светодиодов
mov AL,[LEDStatus] out 60h,AL §PEnd: pop DS popa iret
endp Keyboardlnterrupt
;* УСТАНОВИТЬ НОВЫЙ ОБРАБОТЧИК ПРЕРЫВАНИЯ КЛАВИАТУРЫ *
PROC SetKeyboardInterrupt NEAR pusha push ES
mov AX,0
mov ES.AX
; Запомнить прежний вектор обработчика : прерывания клавиатуры
mov AX,[ES:9*4]
mov [OldKeyboardlnterruptOffset],АХ
mov AX.[ES:9*4+2]
mov [01dKeyboardInterruptSegment],AX
; Установка вектора прерывания на обработчик клавиатуры cliзапретить прерывания
mov АХ,offset Keyboardlnterrupt
mov [ES:9*4],АХ
mov AX.CS
mov [ES:9*4+2].AX
stiразрешить прерывания
pop ES
popa
ret
ENDP SetKeyboardlnterrupt
;* ВОССТАНОВИТЬ ИСХОДНЫЙ ВЕКТОР ПРЕРЫВАНИЯ *
PROC RestoreddKeyboardlnterrupt NEAR pusha
; Настроить регистр ES на таблицу векторов прерываний push ES
mov AX.О
mov ES.AX
; Восстановить прежний вектор обработчика прерывания cli
mov АХ,[OldKeyboardlnterruptOffset]
mov [ES:9*4],AX
mov AX,[01dKeyboardlnterruptSegment]
mov [ES:9*4+2],AX
sti
pop ES
popa
ret
ENDP RestoreddKeyboardlnterrupt
;* ОЖИДАНИЕ ОЧИСТКИ ВХОДНОГО БУФЕРА 18042*
;* При выходе из процедуры:*
;* флаг ZF установлен – нормальное завершение,*
;* флаг ZF сброшен – ошибка тайм-аута.*
proc Wait8042BufferEmpty near push СХ
mov СХ.OFFFFh ;задать число циклов
@@kb: in AL,64h :получить статус
test AL.lOb :буфер i8042 свободен? loopnz
@@kb;если нет, то цикл
pop СХ
; (если при выходе сброшен флаг ZF – ошибка) ret
endp Wait8042BufferEmpty ENOS
; Подключить процедуры вывода данных на экран
Include "listl 02.inc"
END
Следует иметь в виду, что приведенный пример был для наглядности сильно упрошен: драйвер обрабатывает только коды клавиш основной клавиатуры и управляющих клавиш Num Lock и Scroll Lock. Функциональные клавиши, клавиши дополнительной и цифровой клавиатур игнорируются. Из трех клавиш, состояние которых отображается светодиодами, влияние на коды вводимых символов оказывает только Caps Lock, а реакция на Num Lock и Scroll Lock сводится к зажиганию или гашению соответствующих индикаторов.
ВНИМАНИЕ
Запускать все приведенные в данном разделе примеры можно на любом АТ-совместимом персональном компьютере с VGA-совместимым видеоконтроллером. Единственное ограничение: при помощи стандартного драйвера-русификатора DOS (или любого другого) перед запуском примеров должна быть загружена русская кодовая таблица, поскольку при выводе на экран используются сообщения на русском языке.
Источник: Кулаков В. К90 Программирование на аппаратном уровне: специальный справочник (+дискета). 2-е издание. — СПб.: Питер, 2003. — 847 е.: ил.
Похожие посты:
- Более сложные приемы ZObrist-ключи (0)
- Генерация оберток для данных (0)
- Генерация Web-клиента для тестирования ввода данных (0)
- Генерация CGI-сценария для обработки тестовых данных (0)
- Работа с последовательностями (0)
- Исключение рекурсии с помощью выражений for (0)
- Применение типов в целях безопасности и точности выражения намерений (0)



