Электронный учебник по дисциплине "Системное программное обеспечение"


5. Средства ввода информации с клавиатуры

 

Три уровня ввода информации в программу

 

 

 1. Аппаратные и программные средства ввода информации

 Клавиатура содержит специализированный микропроцессор, который при каждом нажатии и отпускании клавиши определяет ее порядковый номер и помещает его в порт 64h (или 60h) программируемого периферийного интерфейса Intel 8042. Младшие 7 бит содержат номер клавиши, а старший бит устанавливается в нуль при нажатии (прямой скэн-код) и единицу при отпускании (обратный скэн-код) клавиши.

Порт 60h является только записываемым и поддерживается для совместимости с ранними моделями персональных компьютеров.

Когда скэн-код записан в порт 64h программируемого периферийного интерфейса, выдается сигнал подтверждения и генерируется прерывание 09h для вызова стандартного обработчика прерываний от клавиатуры.

BIOS анализирует скэн-код и преобразует его.

Если клавиша нажата дольше времени задержки (delay value), микропроцессор клавиатуры генерирует с заданной частотой (typematic rate) прямой скэн-код клавиши.

Контроллер клавиатуры генерирует прерывание по линии 1 (IRQ1) на каждое нажатие и отпускание клавиши. IRQ1 распределена за обработчиком прерывания 09h и обслуживается BIOS.

Порт 64h служит для записи команд и данных, а также для чтения статуса клавиатуры.

Перед посылкой команды клавиатуре BIOS тестирует ее состояние командой in AL,64h для предотвращения ситуаций переполнения буфера или нажатия на клавишу.

Чтобы избежать критических ситуаций, например, при установке частоты генерации кода, следует установить небольшую задержку между двумя операциями записи в порт:

    mov  al,cmd_code

    out  64h,al

    mov  cx,2000h ;приблизительное значение

delay: loop delay

    mov  al,data_value

    out  64h,al

 

Для управления клавиатурой применяются команды:

0FFh - восстановление клавиатуры и запуск диагностики;

0FEh - повторная передача последнего сообщения;

0FDh..0F7h - зарезервировано;

0F6h - установить состояние клавиатуры по умолчанию и продолжить ввод;

0F5h - установить состояние клавиатуры по умолчанию и отменить ввод;

0F4h - клавиатура доступна. Выполняется посылка 'ACK', очищается буфер и запускается ввод;

0F3h - установить частоту генерации и время задержки.

Сначала посылается команда 0F3h, а затем байт данных:

 

Частота генерации устанавливается в соответствии с табл. 1.

 

Биты 0..4

Частота генерации, символов/с

0

30.0

1

26.7

2

24.0

4

20.0

8

15.0

0aH

10.0

0dH

9.2

10H

7.5

14H

5.0

1fH

2.0

 

Недостающие значения определяются интерполяцией.

Первоначально для клавиатуры устанавливается время задержки 0.5 с и частота повторений 10 символов/с.

 

Задержка и частота повторения могут устанавливаться через функцию AH = 03h прерывания 16h BIOS.

0F2h..0EFH - зарезервировано;

0EEh - эхо. Просто посылает значение 0EEh;

0EDh - управление триггерными клавишами и индикаторами. Посылается 0EDh, а затем байт, в котором используются только биты 0..2

 

 

Анализ и преобразование скэн-кода

 Клавиши в зависимости от алгоритма обработки скэн-кода делятся на

·        шифт-клавиши Shift, Alt, Ctrl - правые (right) и левые(left);

·        триггерные клавиши  NumLock, ScrollLock, CapsLock, Insert (Ins), Pause;

·        клавиши c буферизацией расширенного кода;

·        специальные клавиши  PrintScreen,  Ctrl+Alt+Del,  Ctrl+C, Ctrl+Break.

 Состояние шифт- и триггерных клавиш отражается в слове 40:17h (табл. 2). Текущее состояние шифт- и триггерных клавиш используется BIOS-обработчиком прерываний от клавиатуры  при  преобразовании скэн-кода от других клавиш.

При нажатии клавиши c буферизацией расширенного кода в буфер клавиатуры помещается двухбайтовый код (BIOS-код клавиши):

·          младший байт содержит ASCII-код или нуль;

·          старший байт содержит скэн-код или расширенный скэн-код.

Комбинация ASCII-код/скэн-код генерируется, если

1.     Нажата ASCII-клавиша, с учетом Shift и CapsLock;

2.     При одновременном нажатии Ctrl и ASCII-клавиши, а также для клавиш BackSpace, Enter, Tab, Esc. Младший байт имеет код 0..31.

Комбинация 0/расширенный скэн-код генерируется для клавиш F1..F12, Insert (Ins), Delete (Del), Down, Up, Left, Right, Home, End, PgUp, PgDn и их сочетаний с Alt, Shift, Ctrl, а также Аlt+ASCII-символ.

Значение расширенного скэн-кода определяется технической документацией BIOS.

Расширенный скэн-код и скэн-код не совпадают.

 

Бит

Состояние

 

40:17h

0

Hажата Right Shift

1

Hажата Left Shift

2

Hажата Right Ctrl

3

Hажата Right Alt

4

Зафиксирован скроллинг экрана (ScrollLock – включен)

5

Включена цифровая клавиатура (NumLock  - включен)

6

Зафиксирован верхний регистр (CapsLock  - включен)

7

Включен режим вставки     (Ins    - включен)

 

40:18h

0

Hажата Left Ctrl

1

Hажата Left Alt

2

Hажата System

3

Включен режим Pause (Ctrl+NumLock)

4

Hажата ScrollLock

5

Hажата NumLock

6

Hажата CapsLock

7

Hажата Ins

 

Hажатие на специальную клавишу PrintScrn приводит к прерыванию 5h, которое стандартно закреплено за функцией печати текстового экрана.

Одновременное нажатие Ctrl+Alt+Del запускает программу начальной загрузки операционной системы без тестирования аппаратуры (мягкая перезагрузка).

Использование комбинации клавиш Ctrl+C (Ctrl+Break) позволяет по адресу 0047h записать 80h (флаг сигнализации о желании приостановить выполнение текущей программы). Этот флаг проверяется функциями, которые способны генерировать прерывание 23h.

 

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

Буфер клавиатуры занимает 32 байта (40:1Eh .. 40:3Eh).

Запись выполняет обработчик прерывания 09h, чтение - обработчик прерывания 16h.

Буфер рассчитан на 15 двухбайтовых кодов вводимой строки и один двухбайтовый код для клавиши Enter, нажатие на которую служит признаком завершения ввода для интерпретатора команд ОС.

Буфер организован как кольцевая очередь, доступ к которой осуществляется через два указателя, расположенных по адресам  0040:001Ah - указатель "головы" (Head Pointer),  0040:001Ch - указатель "хвоста" (Tail Pointer).

Значения в указателях равны смещению от сегмента 0040h. Tail Pointer (хвост) показывает на первое свободное слово буфера, Head Pointer (голова) показывает на начало очереди.

 

Схема работы буфера

При нажатии на клавишу код записывается в буфер и указатель "хвоста" увеличивается на два. Если значение указателя "хвоста" больше 003Eh, то буфер считается переполненным, новые коды не принимаются, и из динамика компьютера звучит предупреждающий сигнал.

Обработчик прерывания 16h использует указатели "головы" и "хвоста" для ввода с клавиатуры.

Функция АH = 0 (чтение буфера с разрушением информации) позволяет прочитать из буфера два байта и увеличивает значение указатель "головы" на два.

Если значения указателей равны, это говорит о том, что буфер пуст. Обработчик прерывания выполняет бесконечный цикл ожидания до неравенства значений указателей.

Функция АH = 1 (чтение без разрушения) служит для передачи слова в программу. Значение указателя "головы" не меняется.

Если значения указателей совпадают, то выставляется флаг CF = 1 и обработчик прерывания 16h аварийно завершается.

Буфер клавиатуры - это классический пример использования кольцевой очереди для организации асинхронного взаимодействия двух программ по схеме "производитель-потребитель" (обработчик прерывания 09h производит данные, а 16h - потребляет).

  

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

Все приложения, написанные для Microsoft Windows, способны осуществлять ввод данных с клавиатуры. В основу работы приложения с клавиатурой положена следующая модель.

 

 

Windows обеспечивает независимую от устройств поддержку клавиатурного ввода с помощью установки драйвера клавиатуры. Также поддерживается языковая независимость входного потока. Драйвер клавиатуры получает скэн-коды, которые перетранслируются в виртуальные коды клавиш (virtual-key code) и формируют сообщения, пересылаемые в очередь системных сообщений.

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

Задача может вызвать функцию GetFocus, чтобы определить, какое окно имеет в настоящий момент фокус ввода. Передача фокуса выполняется функцией SetFocus.

При передаче фокуса от одного окна другому система посылает сообщение WM_KILLFOCUS тому окну, которое теряет фокус, и WM_SETFOCUS окну, получающему фокус.

 

Hажатие на клавишу приводит к помещению в очередь сообщений WM_KEYDOWN или WM_SYSKEYDOWN, которые передаются окну, имеющему фокус ввода.

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

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

При этом проверяется виртуальный код и, если он соответствует символу, возвращается кодовый эквивалент с учетом состояния SHIFT и CAPS LOCK клавиш.

Генерируется символьное сообщение, которое помещается в вершину очереди сообщений.

Следующая итерация цикла обработки сообщений забирает его и передает ожидающему ввода окну.

 

Поддержка горячих клавиш (Hot-Key)

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

Приложение использует горячие клавиши для создания высокоприоритетного клавиатурного ввода. Hапример, определяя горячую клавишу из комбинации CTRL+C key, приложение может обеспечить аварийное завершение некоторой операции.

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

 

Языки и локализация

 Hа уровне Windows API поддерживается работа с национальными языками и диалектами. Приложения обычно используют локализацию (т.е. установку национального языка) для ввода и отображения информации. Каждая кодовая таблица оснащается идентификатором, который определяет язык.

Обычно приложение само не манипулирует языками. Hапротив, пользователь может устанавливать языковую кодовую таблицу или переключаться между ними.

Функция ActivateKeyboardLayout устанавливает входной язык для текущей задачи. Идентификаторы кодовых страниц могут быть получены от функций LoadKeyboardLayout или GetKeyboardLayoutList.

 

Hosted by uCoz