5.10.1. Клавиатура

Контроллеру клавиатуры соответствуют порты с номерами от 60h до 6Fh, хотя для всех стандартных операций достаточно портов и 64h для чтения - регистр состояния клавиатуры, возвращает следующий байт: бит 7: ошибка четности при передаче данных с клавиатуры

бит 6: тайм-аут при приеме бит 5: тайм-аут при передаче

; -Переменные для временного хранения ; регистров.бит 4: клавиатура закрыта ключом

бит 3: данные, записанные в регистр ввода, - команда

бит 2: самотестирование закончено

бит 1: в буфере ввода есть данные (для контроллера клавиатуры) бит 0: в буфере вывода есть данные (для компьютера)

При записи в этот порт он играет роль дополнительного регистра управления, клавиатурой, но его команды сильно различаются для разных плат и разных BIOS, и мы не будем его подробно рассматривать.

61h для чтения и записи - регистр управления клавиатурой. Если в старший бит этого порта записать значение 1, клавиатура будет заблокирована, если 0 -разблокирована. Другие биты этого порта менять нельзя, так как они управ­ляют иными устройствами (в частности динамиком). Чтобы изменить состо­яние клавиатуры, надо считать байт из порта, изменить бит 7 и снова запи­сать в порт 61h этот байт.

60h для чтения — порт данных клавиатуры. При чтении из него можно получить скан-код последней нажатой клавиши (см. приложение 1) - именно так лучше всего реализовывать резидентные программы, перехватывающие прерывание потому что по этому коду можно определять момент нажатия и отпус­кания любой клавиши, включая такие клавиши, как Shift, Ctrl, Alt или даже Pause (скан-код отпускания клавиши равен скан-коду нажатия плюс 80h):

int09h_handler:

in

cmp jne

[... ]

not_our_key: jmp

al,60h al,hot_key not_our_key

old_int09h

; Прочитать скан-код клавиши. ; Если это наша "горячая" клавиша, ; перейти к нашему обработчику.

; Наши действия здесь.

;  Вызов старого обработчика.

Мы пока не можем завершить обработчик просто командой ПРЕТ, потому,что, во-первых, обработчик аппаратного прерывания клавиатуры должен установить бит 7 порта 61п, а затем вернуть его в исходное состояние, например так: .

in

push

or

out

pop

out

al,61h

ax

al,80h

61h,al

ax

61h,al

Во-вторых, он должен сообщить контроллеру прерываний, что обработка ап­паратного прерывания закончилась командами

mov out al,20h,

20h,al

60п для записи - регистр управления клавиатурой. Байт, записанный в этот порт (если оит 1 в порту 64Ь равен 0), интерпретируется как команда. Некоторыетш

 

команды состоят из более чем одного байта - тогда следует дождаться обну­ления этого бита еще раз перед тем, как посылать следующий байт. Перечис­лим наиболее стандартные команды.

Команда OEDh 0?h - изменить состояние светодиодов клавиатуры. Второй байт этой команды определяет новое состояние:

бит 0: состояние Scroll Lock (1 - включена, 0 - выключена)

бит 1: состояние Num Lock

бит 2: состояние Caps Lock

При этом состояние переключателей, которое хранит BIOS в байтах состоя­ния клавиатуры, не изменяется, и при первой возможности обработчик прерыва­ния клавиатуры BIOS восстановит состояние светодиодов.

Команда OEEh - эхо-запрос. Клавиатура отвечает скан-кодом OEEh.

Команда        ??h - установить параметры режима автоповтора: бит 7 второго байта команды: О

биты 6-5: устанавливают паузу перед началом автоповтора: 00b= 250ms, 01b- 500ms, 10b = 750ms, lib = 1000ms

биты 4-0: устанавливают скорость автоповтора (символов в секунду):

00000b =

30,0

01111b =

8,0

00010b=

24,0

10010b=

6,0

00100b =

20,0

10100b-

5,0

00111b-

16,0

10111b-

4,0

01000b -

15,0

11010b-

3,0

01010b =

12,0 11111b-

2,0

01100b -

10,0

 

 

Все промежуточные значения также имеют смысл и соответствуют промежу­точным скоростям, например OOOOlb = 26,7.

Команда OF4h - включить клавиатуру.

Команда        - выключить клавиатуру.

Команда        - установить параметры по умолчанию.

Команда OFEh - послать последний скан-код еще раз.

Команда - выполнить самотестирование.

Клавиатура отвечает на все команды, кроме OEEh и OFEh, скан-кодом OFAh

(подтверждение), который поглощается стандартным обработчиком BIOS, поэто­му, если мы не замещаем его полностью, об обработке OFAh можно не беспокоиться.

В качестве примера работы с клавиатурой напрямую рассмотрим простую про­грамму, выполняющую переключение светодиодов.

; mig.asm • • ,

;  Циклически переключает светодиоды клавиатуры.

.model tiny

org . code 100b ;

приемы программирования

start

proc     near •

 

mov

ah, 2

Функция 02 прерывания 1АИ:

int

.

получитв текущее время.

mov

ch, dh

Сохранитв текущую секунду в СН.

mov

cl,0100b

СЪ = состояние светодиодов клавиатуры

main loop:

 

 

call

change_LEOs

Установитв светодиоды в соответствии

shl

cl,1

Следующий светодиод.

test

cl,1000b

Если единица вышла в бит 3,

jz

continue

 

mov

cl,0001b

вернутв ее в бит 0.

continue:

 

 

mov

ah, 1

Проверить,  не была ли нажата клавиша.

int

16h

 

jnz

exit_loop

Если да - выйти из программы.

push

cx

 

mov

ah, 2

Функция 02 прерывания 1Ап.

int

1Ah

Получитв текущее время.

pop

cx

 

cmp

ch.dh

Сравнить текущую секунду в ОН с СН.

mov

ch.dh

Скопироватв ее в любом случае.

je

continue

Если это была та же самая секунда -

 

 

не переключатв светодиоды.

jmp

short

Иначе - переключитв светодиоды.

exit_loop:

 

 

mov

ah, 0

Выход из цикла - была нажата клавиша.

' int

16h

; Считатв ее

ret

 

и завершитв программу.

start

endp

 

; Процедура

change_LEDs.

 

;  Устанавливает состояние светодиодов клавиатуры в соответствии с числом

change LEDs

proc near

 

call

wait_KBin

Ожидание возможности посылки команды.

mov

al.OEDh

 

out

60h,al

Команда клавиатуры ЕОЬ.

call

wait_KBin

Ожидание возможности посылки команды.

mov

al.cl

 

out

60h,al

Новое состояние светодиодов.

ret

 

 

change_LEDs

endp

 

; Процедура

 

;   Ожидание возможности ввода команды для клавиатуры.

wait KBin

proc near

 

in

al,64h

слово состояния.

test

al,0010b

Бит 1 равен 1?

jnz

wait_KBin

Если нет - ждатв.

ret

 

Если да - выйти.

wait KBin

endp

 

end

start