Главная » Ассемблер, Железо » Непосредственная работа с контроллером клавиатуры

0

Реальная необходимость в непосредственной работе с клавиатурой возникает в том случае, если вы создаете программу, которая переводит процессор из реального режима в защищенный, а затем выполняет в защищенном режиме всю дальнейшую работу. Переход в защищенный режим приводит к тому, что функции 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 е.: ил.

По теме:

  • Комментарии