Аппаратное обеспечение персонального компьютера© Александр Фролов, Григорий ФроловТом 33, М.: Диалог-МИФИ, 1997, 304 стр. Средства BIOS для работы с клавиатуройНабор функций для работы с клавиатурой, предоставляемый в распоряжение программиста прерыванием BIOS INT 16h, включает в себя функции для выборки кода нажатого символа из буфера с ожиданием нажатия, функции для проверки содержимого буфера и для управления содержимым буфера, функции для изменения скоростных характеристик клавиатуры. Чтение символа с ожиданиемФункция 00h выполняет чтение кода символа из буфера клавиатуры, если он там есть. Если буфер клавиатуры пуст, программа переводится в состояние ожидания до тех пор, пока не будет нажата какая-нибудь клавиша. Скан-код и код ASCII нажатой клавиши передаются программе. Приведем формат вызова функции:
Приведем таблицу скан-кодов:
Для остальных клавиш функция 00h прерывания INT 16h возвращает расширенный код ASCII:
В следующей таблице приведены скан-коды клавиш, имеющихся только на 101-клавишной клавиатуре:
Буква "Д" здесь обозначает дополнительную клавиатуру. Программа KBDSCANДля демонстрации использования функции 00h прерывания INT 16h мы подготовили программу, выводящую на экран скан-коды и коды ASCII нажимаемых клавиш (листинг 2.2). Листинг 2.2. Файл kbdscan\kbdscan.c // ===================================================== // Просмотр клавиатурных скан-кодов и кодов ASCII // // (C) Фролов А.В, 1997 // // E-mail: frolov@glas.apc.org // WWW: http://www.glasnet.ru/~frolov // или // http://www.dials.ccas.ru/frolov // ===================================================== #include <stdio.h> #include <dos.h> int main(void) { union REGS rg; printf("KBDSCAN, (c) A. Frolov, 1997\n" "Press <ESC> to exit\n"); for(;;) { // Вызываем прерывание INT 16h rg.h.ah = 0; int86(0x16, &rg, &rg); // Выводим на экран содержимое регистров AH и AL, // содержащих, соответственно, скан-код и код ASCII // нажатой клавиши printf("\nScan = %02.2X Ascii = %02.2X", rg.h.ah, rg.h.al); // Если была нажата клавиша ESC, завершаем работу // программы if(rg.h.ah == 1) break; } return 0; } Проверка буфера на наличие в нем символовФункция 01h поможет вам проверить состояние буфера клавиатуры - есть там коды нажатых клавиш или нет. При этом программа не переводится в состояние ожидания, даже если буфер клавиатуры пуст. В этом случае в регистре флагов флаг ZF устанавливается в единицу и управление возвращается программе. Формат вызова функции представлен ниже:
Эту функцию удобно использовать во время выполнения какого-либо длительного процесса (например, форматирования диска или передачи данных по линии связи) для прерывания этого процесса по запросу пользователя. Кроме того, функцию 01h можно применять вместе с функцией 00h для сброса содержимого клавиатурного буфера. Для этого в цикле повторяют вызов функции 01h, вслед за которым идет вызов функции 00h при условии, что буфер клавиатуры не пуст. Сброс буфера клавиатуры полезно выполнять перед вводом ответственной информации, так как если пользователь случайно нажмет одну и ту же клавишу несколько раз, в буфере клавиатуры могут оказаться лишние символы. Программа CHKBUFПриведем исходный текст программы CHKBUF, выводящей на экран в цикле символ '*' (листинг 2.3). Если нажать любую клавишу, кроме <Esc>, программа выводит на экран строку текста - инструкцию для завершения работы программы. Если же нажать на клавишу <Esc>, работа программы будет завершена. Листинг 2.3. Файл chkbuf\chkbuf.c // ===================================================== // Демонстрация способа проверки буфера клавиатуры // // (C) Фролов А.В, 1997 // // E-mail: frolov@glas.apc.org // WWW: http://www.glasnet.ru/~frolov // или // http://www.dials.ccas.ru/frolov // ===================================================== #include <stdio.h> #include <dos.h> int main(void) { union REGS rg; int i, zflag; printf("CHKBUF, (c) A. Frolov, 1997\n"); for(;;) { // Выводим в цикле символ '*' putchar('*'); // Небольшая задержка во времени for(i=0; i<30000; i++); // Вызываем прерывание INT 16h для проверки буфера // клавиатуры. Устанавливаем флаг, который будет сброшен // при нажатии на любую клавишу zflag = 1; _asm { mov ax, 0100h int 16h // Если клавишу не нажимали, // продолжаем выполнение программы jz nokey // В противном случае сбрасываем флаг mov zflag, 0 nokey: } if(zflag == 0) { // Если флаг сброшен, читаем код нажатой клавиши из // буфера при помощи функции 01h прерывания INT 16h rg.h.ah = 0; int86(0x16, &rg, &rg); // Если была нажата клавиша <Esc>, // завершаем работу программы if(rg.h.ah == 1) { // Выводим на экран содержимое регистров AH и AL, // содержащих, соответственно, скан-код и код ASCII // нажатой клавиши printf("\nScan = %02.2X Ascii = %02.2X", rg.h.ah, rg.h.al); break; } else printf("\nPress <ESC> to exit\n"); } } return 0; } Получение состояния переключающих клавишФункция 02h возвращает в регистре AL состояние переключающих клавиш, таких как <Shift>, <Control>, <Alt>, <ScrollLock>, <NumLock>, <CapsLock>, <Insert>:
Формат байта состояния соответствует формату байта, находящегося в области данных BIOS по адресу 0000h:0417h:
Функция 02h может быть использована для анализа текущего состояния переключающих клавиш. Ниже показан фрагмент кода, в котором проверяется состояние клавиши <CapsLock>: rg.h.ah = 2; int86(0x16, &rg, &rg); if((rg.h.al & 0x40) == 0) { // Клавиша <CapsLock> не нажата, // соответствующий светодиод не горит . . . } else { // Клавиша <CapsLock> нажата . . . } Установка временных характеристик клавиатурыМы уже рассказывали о возможности изменения временных характеристик клавиатуры. Если BIOS, установленная в вашей машине, изготовлена после 15 декабря 1985 года, вы можете воспользоваться функцией 03h для ускорения (или замедления) работы клавиатуры:
Период автоповтора задается следующим образом:
Для задержки включения режима автоповтора вы можете указывать следующие значения:
В качестве примера приведем два фрагмента программы. Первый фрагмент увеличивает быстродействие клавиатуры до его верхнего предела, второй восстанавливает исходные значения временных характеристик. union REGS rg; . . . rg.h.al = 5; rg.h.ah = 3; // Устанавливаем максимальное быстродействие клавиатуры rg.h.bl = 0; rg.h.bh = 0; int86(0x16, &rg, &rg); . . . // Восстанавливаем исходное быстродействие клавиатуры rg.h.bl = 0xa; rg.h.bh = 1; int86(0x16, &rg, &rg); Запись символов в буфер клавиатурыС помощью функции 05h можно вставить символы в буфер клавиатуры, как будто они были введены оператором.
Приведенная ниже фрагмент программы записывает в буфер клавиатуры пять символов '*'. Если запустить программу, соедржащую этот фрагмент кода, а затем посмотреть на системное приглашение, то вы увидите что-нибудь похожее на C:\>*****. union REGS rg; int i; for(i=0; i<5; i++) { rg.h.ah = 5; rg.h.cl = '*'; rg.h.ch = 9; int86(0x16, &rg, &rg); } Чтение символа с ожиданием для 101-клавишной клавиатурыФункция 10h, предназначенная для чтения символа с ожиданием, полностью аналогична функции 00h, но она может работать только с клавиатурой, имеющей 101 клавишу. Приведем формат вызова функции:
Функция определена для BIOS, изготовленной после 15 декабря 1985 года. Проверка буфера на наличие в нем символов для 101-клавишной клавиатурыФункция 11h полностью аналогична функции 01h, но она предназначена для работы с клавиатурой, имеющей 101 клавишу:
Эта функция определена для BIOS, изготовленной после 15 декабря 1985 года. Получение состояния переключающих клавиш для 101-клавишной клавиатурыФункция 12h возвращает в регистре AL состояние переключающих клавиш, таких как <Shift>, <Control>, <Alt>, <ScrollLock>, <NumLock>, <CapsLock>, <Insert> и используется только для 101-клавишных клавиатур:
Эта функция определена для BIOS, изготовленной после 15 декабря 1985 года. |