Описание логической структуры




Практикум №2.

«Управление клавиатурой»

Цель работы: Изучение организации и принципов работы клавиатуры и закрепление практических навыков управления ею.

 

Краткие теоретические сведения

Сочетание «горячих» клавиш (клавиша быстрого доступа; англ. keyboard shortcut)— разновидность интерфейса взаимодействия с вычислительным устройством (компьютером, калькулятором), представляющая собой нажатие кнопки/клавиши (или сочетания клавиш) на клавиатуре, которому назначено (запрограммировано) некое действие — команды (операции), исполняемые данной системой. Как правило, частично дублирует интерфейс меню или кнопок и служит для значительного ускорения работы, также — увеличения количества возможных действий, выполняемых с помощью клавиатуры.

На персональных компьютерах чаще всего в сочетаниях используются клавиши Ctrl, Alt, ⇧Shift, а также Win или Command. Их часто называют клавиши-модификаторы. В сочетаниях можно зажимать не только одну из этих клавиш, а несколько одновременно.

Стоит отметить, что клавиша-модификатор (или управляющая клавиша) принципиально отличается от иных клавиш тем, что может:

· неограниченно долго находиться в зажатом (активном) состоянии, и

· будучи зажатой, не блокировать действия остальных клавиш — как модификаторов, так и обычных.

Такие клавиши обычно имеют отдельный вывод контроллера клавиатуры, в отличие от алфавитно-цифровых, организованных матрично из-за экономии выводов контроллера. Матричная клавиатура обычно рассчитана на нажатие клавиш только поодиночке, поэтому, например, одновременное зажатие Q и W ни к чему хорошему не приведёт. Для оповещения оператора о подобных проблемах в DOS выдавался сигнал на динамик ЭВМ при зажатии нескольких не управляющих клавиш.

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

Возможные возвращаемые значения функции установим: 1 (задание параметров правильное) и 0 (задание не правильное). Эти значения при обращениях к функции можно будет интерпретировать как «истина» или «ложь».

Заметим, что интерпретация конфигурации параметров как правильная/неправильная и выбор реакции на неправильное задание — дело исполнителя. Но исполнитель должен строго выполнять принятые правила. Возможен также случай, когда выходная строка выйдет большей длины, чем для нее отведено места в памяти. Однако, поскольку нашей функции неизвестен размер памяти, отведенный для строки, функция не может распознать и обработать этот случай — так же ведут себя и библиотечные функции языка C.

Алгоритм решения задачи

Шаг 1: Запомнить адрес старого обработчика прерывания 9h, вызывая функцию readvect(in) с параметром in=9.

Шаг 2: Записать в таблицу векторов прерываний адрес нового обработчика прерывания с помощью функции writevect().

Шаг 3: Прочитать флаг состояния клавиатуры: два байта по адресу 0040:0017: byte17 = peekb(0x40, 0x17).

Шаг 4: Прочитать флаг состояния клавиатуры: два байта по адресу 0040:0018: byte18 = peekb(0x40, 0x18).

Шаг 4: Выделить бит 1 в флаге по адресу 0040:0017: byte17&mask

(если он равен 1, то нажата клавиша левый Shift).

Шаг 5: Проверить, нажата ли комбинация клавиш CTRL+SHIFT+[3]. Для этого проверяется условие: (inportb(0x60) == F3_code) && (byte17&mask) && (byte17&mask17) && (!(byte18&mask18)).

Если byte17&mask17 равен 1, то нажата клавиша CTRL.

Если byte18&mask18 равен 1, то нажата клавиша SHIFT.

Если inportb(0x60) равен F3_code, то нажата клавиша «3».

Шаг 6: Если выполняется условие из шага 5, проверить, равен ли флаг блокирования нулю (разблокирована ли клавиатура).

Шаг 7: При выполнении условия из шага 6, клавиатура блокируется (f=1), иначе происходит разблокировка.

Шаг 8: Проверить условие: (f == 1) && (inportb(0x60) == key3_code).

Шаг 9: В случае выполнения условия из шага 8 послать подтверждение приема в клавиатуру. Для этого в порт 61h на короткое время выставить «1» по шине старшего разряда:

c = inportb(0x61);

outportb(0x61, c | 0x80);

outportb(0x61, c).

Сбросить контроллер прерываний, посылая код 20h в порт 20h: outportb(0x20, 0x20).

Шаг 10: Вызов обработчика прерываний(*old9()).

Шаг 11: Записать в таблицу векторов прерываний адрес нового обработчика прерывания с помощью функции writevect.

Схема алгоритма изображена на рис. 2.

Тестовый пример

Дано: комбинации «горячих» клавиш CTRL+SHIFT+[Любая клавиша]

Необходимо: Разработать программу обработки прерывания от клавиатуры, которая должна:

• при первом нажатии «горячей» комбинации переходить в режим блокировки ввода заданной клавиши, при втором — отменять этот режим;

• системная обработка всех других клавиш нарушаться не должна.

Для блокировки символа «3» необходимо нажать комбинацию клавиш CTRL+SHIFT+[Любая клавиша]. Для снятия блокировки также использовать комбинацию клавиш CTRL+SHIFT+[Любая клавиша].

Рис.1 – Работа программы

 

Описание логической структуры

Программа состоит из одного программного модуля — файл ConsoleApplication1. В состав модуля входит функция — main. Общих переменных в программе нет. Макроконстантой Nопределена максимальная длина строки — 80. Функция main является главной функцией программы, она предназначена для ввода исходных данных и вывода результатов.

Определим состав параметров функции. Глобальные переменные программы: old9 — адрес старого обработчика прерывания 9h; key3_code — скан-код клавиши «3», которая будет блокироваться/разблокироваться при каждом нажатии «горячей» комбинации клавиш; f — флаг, который при каждом нажатии «горячей» комбинации клавиш переключается из состояния 0 в 1 или из 1 в 0 (состояние 1 означает, что клавиша «3» заблокирована); rr и sr — переменные, которые используются для задания значений регистров общего назначения и сегментных регистров соответственно при вызове прерывания.

В главной программе использует символьный массив string для проверки работы программы.

Переменные процедуры обработки прерывания 9h:

· c — переменная, которая используется для подтверждения приема из клавиатуры, в случае, если была нажата клавиша «3», а флаг f показывал, что эта клавиша заблокирована;

 

Рис. 2 – Схема алгоритма

 

· x, y — переменные, которые используются для сохранения координат курсора на экране в момент вызова процедуры обработки прерывания;

· byte17 — байт флага состояния клавиатуры в области данных BIOS по адресу 0040:0017;

· byte18 — байт флага состояния клавиатуры в области данных BIOS по адресу 0040:0018;

· mask — маска, которая используется для определения нажатия клавиши левый Shift (в этом случае бит 1 в byte17 установлен в 1);

· mask17 — маска, которая используется для определения нажатия клавиши Сtrl (в этом случае бит 2 в byte17 установлен в 1);

· mask18 — маска, которая используется для определения нажатия клавиши левый Сtrl (в этом случае бит 0 в byte18 установлен в 1);

Варианты заданий

Nп/п Сочетания "горячих" клавиш Клавиша, которая блокируется
Shift Ctrl Alt
Лев. Пр. Лев. Пр. Лев. Пр.
  + +          
  +   +        
    +     +    
  +       +    
  +         +  
    + +        
    +     +    
    +   +      
    +       +  
  +   +        

6. Контрольные вопросы

 

1. Какое главное качество языка С?

2. Как представляется признак конца стоки в языке С?

3. Что такое аппаратное прерывание?

4. Что выполняет функция конкатенации?

5. Какой библиотечной функции является аналогичной функция конкатенации?

 

Приложение

/*_________Управление клавиатурой_______________*/

/* Подключение стандартных заголовков */

#include<dos.h>

void interrupt(*old9)(); /* Старый обработчик прерывания 9h */

void interruptnew9(); /* Новый обработчик прерывания 9h */

void *readvect(int in); /* Чтение вектора */

void writevect(int in, void *h); /* Запись вектора */

unsigned char F3_code = 61; /* scan_code "F3" */

unsigned char key3_code = 4;/* scan_code "3" */

char f = 0; /* Флаг */

union REGS rr;

struct SREGS sr;

/*________________________________________________*/

void main()

{

charstring[80]; /* Буфер для ввода текста */

textbackground(0);

clrscr();

textattr(0x0a);

cprintf("_______________");

cprintf("_______________");

cprintf("_______________");

cprintf(" Управление клавиатурой ");

cout<<L"Введите любой текст. Комбинация клавиш CTRL+SHIFT+[Любая клавиша] запретят к вводу символ '3'.\n";

cprintf("_______________");

old9 = readvect(9);

writevect(9, new9);

textattr(0x0c);

cprintf("\n\n\r\"горячая\" комбинация: ");

textattr(0x0a);

cprintf("Left Shift, Left Ctrl, [любаяклавиша]\n\r");

textattr(0x0b);

cprintf("Клавиша, котораяблокируется: ");

textattr(0x0f);

cprintf("3");

textattr(0x07);

cprintf("\r\nВводите строку символов>");

scanf("%s", string);

writevect(9, old9);

}

/* Чтение вектора */

void *readvect(intin)

{

rr.h.ah = 0x35;

rr.h.al = in;

intdosx(&rr, &rr, &sr);

return(MK_FP(sr.es, rr.x.bx));

}

/* Записьвектора */

void writevect(int in, void *h)

{

rr.h.ah = 0x25;

rr.h.al = in;

sr.ds = FP_SEG(h);

rr.x.dx = FP_OFF(h);

intdosx(&rr, &rr, &sr);

}

/* Новый обработчик 9_го прерыванмя */

void interrupt new9()

{

unsigned char c, x, y;

unsigned char byte17, byte18;

unsigned char mask = 0x02;

unsigned char mask17 = 0x04;

unsigned char mask18 = 0x01;

byte17 = peekb(0x40, 0x17);

byte18 = peekb(0x40, 0x18);

if ((inportb(0x60) == F3_code) && (byte17&mask) &&

(byte17&mask17) &&(!(byte18&mask18)))

{

cputs("\7");

x = wherex();

y = wherey();

gotoxy(55, 3);

textattr(0x1e);

if (f == 0)

{

f = 1;

cprintf("Cимвол '3' запрещен, снова нажмите комбинацию клавиш CTRL+SHIFT+[Любая клавиша] чтобы снять запрет.");

}

else

{

f = 0;

cprintf("Запрет снят, вы снова моежет использовать символ '3'.");

}

gotoxy(x, y);

textattr(0x07);

(*old9)();

}

if ((f == 1) && (inportb(0x60) == key3_code))

{

c = inportb(0x61);

outportb(0x61, c | 0x80);

outportb(0x61, c);

outportb(0x20, 0x20);

}

else

(*old9)();

}

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2019-05-21 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: