
Ввод информации с клавиатуры средствами bios
Интерфейсом программ в персональном компьютере с клавиатурой является прерывание 16h BIOS. Далее приводится описание его функций.
АН = 00h - чтение с ожиданием двухбайтового кода из буфера клавиатуры. Прочитанный код возвращается в регистре АХ: младший байт - в регистре AL, старший - в АН. Если нажата ASCII-клавиша, в AL помещается ASCII-код символа, в АН - скэн-код. При нажатии специальных клавиш AL равен 0, а в АН возвращается расширенный скэн-код.
АН = 0lh - чтение без ожидания двухбайтового кода из буфера клавиатуры. Если буфер пуст, в 1 выставляется флаг нуля ZF. В противном случае в АХ возвращается двухбайтовый код из буфера клавиатуры, но продвижение указателя "головы" буфера не производится, т.е. код "остается" в буфере.
АН = 02h - определение состояния шифт- и триггерных клавиш. В регистре AL возвращается содержимое байта по адресу 40:17h (см. табл. 4.1).
Функция АН = 05h не имеет аналогов в библиотеке Turbo С и может использоваться для имитации нажатии клавиш в демонстрационных программах, программах переноса текста и т.д.
Функции АН = 10 - 12h являются аналогами функций 00 - 02h, но предназначены для использования в компьютерах с клавиатурой 101 /102 клавиши.
Функции АН = 00 - 02h прерывания 16h BIOS положены в основу функции bioskey() библиотеки Turbo С. Далее следует описание этой функции.
int bioskey(int cmd)
Обращается в зависимости от значения в cmd к функциям АН = 00 - 02h прерывания 16h. Возвращаемое функцией значение повторяет значение регистра АХ при выходе из прерывания
Алгоритмы
Программа, написанная для первого задания, реализует следующий алгоритм:
Подключить библиотеки conio.h и dos.h для работы с консолью и DOS.
Определить константы для задания границ окна, в котором будет перемещаться символ ‘*’.
Объявить и инициализировать переменные для хранения координат и скорости символа.
Очистить экран и изменить координаты окна.
Переместить курсор в начальную позицию символа.
Запустить бесконечный цикл, в котором будет происходить следующее:
Проверить, была ли нажата клавиша на клавиатуре.
Если была нажата клавиша, то считать ее код и выполнить действие в зависимости от кода:
Если была нажата расширенная клавиша, то считать следующий символ и выполнить действие в зависимости от символа:
Если была нажата ↑, то уменьшить координату y, если не достигнута верхняя граница окна.
Если была нажата ↓, то увеличить координату y, если не достигнута нижняя граница окна.
Если была нажата ←, то уменьшить координату x, если не достигнута левая граница окна.
Если была нажата →, то увеличить координату x, если не достигнута правая граница окна.
Если был нажат Escape, то завершить программу.
Переместить курсор на текущую позицию символа и вывести символ ‘@’.
Задержать выполнение программы на 100 миллисекунд.
Текст программы
1 задаиие
#include<conio.h>
#include<dos.h>
#include<stdio.h>
int main()
{
int ch, x = 1, y = 1;
textbackground(8);
clrscr();
window(25, 5, 55, 15);
textbackground(13);
textcolor(15);
_setcursortype (_NOCURSOR);
do
{
clrscr();
gotoxy(x, y);
cprintf("@");
ch = getch();
switch(ch)
{
case 72: //up
if (y > 1)
y--;
else if (y == 1)
{
sound(100);
delay(100);
nosound();
y = 11;
}
break;
case 80: //down
if (y <= 10)
y++;
else if (y > 10)
{
sound(100);
delay(100);
nosound();
y = 1;
}
break;
case 77: //right
if (x <= 30)
x++;
else if (x > 30)
{
sound(100);
delay(100);
nosound();
x = 1;
}
break;
case 75: //left
if (x > 1)
x--;
else if (x == 1)
{
sound(100);
delay(100);
nosound();
x = 31;
}
break;
default: break;
}
} while (ch != 27);
return 0;
}
2 задание
#include <stdio.h>
#include <conio.h>
#include <dos.h>
int getkey();
void sound(int, int);
void tm_sound(int freq, int time);
// Массив частот
int PartA_1[] =
{
330, 494, 740, 587, 659, 494, 392, 494,
330, 494, 740, 784, 880, 784, 740, 587,
330, 494, 740, 587, 659, 494, 392, 494,
330, 494, 740, 784, 880, 784, 740, 587, 0
};
int PartA_2[] =
{
131, 262, 740, 587, 659, 494, 392, 494,
124, 247, 740, 784, 880, 784, 740, 587,
165, 330, 740, 587, 659, 494, 392, 494,
165, 330, 740, 784, 880, 784, 740, 587, 0
};
// Массив длительностей
int delPartA_1[] =
{
428, 428, 428, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428, 428, 428, 0
};
int delPartA_2[] =
{
428, 428, 428, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428, 428, 428, 0
};
//--------------//
int PartB_1[] =
{
165, 494, 659, 587, 659, 494,
220, 494, 370, 392, 156, 370,
165, 494, 659, 587, 659, 330, 294,
131, 494, 220, 247, 124, 370, 0
};
int PartB_2[] =
{
165, 494, 587, 740, 659, 494,
131, 494, 294, 494, 262, 494,
185, 220, 294, 330, 370, 294,
131, 494, 440, 740, 784, 740, 0
};
int delPartB_1[] =
{
428, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 214, 214,
428, 428, 428, 428, 428, 428, 0
};
int delPartB_2[] =
{
428, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428, 0
};
//--------------//
int PartC_1[] =
{
880, 494, 880, 494, 196, 880,
740, 494, 294, 784, 740, 784,
740, 494, 440, 880, 392, 494,
659, 494, 440, 740, 784, 740, 0
};
int delPartC_1[] =
{
428, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428, 0
};
int PartC_2[] =
{
880, 494, 880, 494, 392, 880,
740, 494, 294, 784, 740, 784,
740, 494, 440, 880, 392, 494,
659, 494, 440, 494, 698, 784, 0
};
int delPartC_2[] =
{
428, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428, 0
};
//--------------//
int delPartD[] =
{
107, 107, 1700, 858,
428, 428, 858, 858, 858,
428, 428, 428, 428, 428, 428, 428, 428,
428, 428, 428, 428, 428, 428, 428, 1700, 0
};
int PartD[] =
{
440, 523, 880, 349,
523, 587, 659, 587, 523,
494, 659, 740, 587, 659, 494, 392, 494,
330, 494, 740, 784, 880, 784, 740, 587, 0
};
int main(void)
{
int i;
int ch, x = 1, y = 1;
textbackground(8);
clrscr();
window(25, 5, 55, 15);
textbackground(13);
textcolor(15);
_setcursortype (_NOCURSOR);
do
{
clrscr();
gotoxy(x, y);
cprintf("@");
ch = getkey();
switch(ch)
{
case 32:
do{
for (i = 0; PartA_1[i] != 0; i++)
tm_sound(PartA_1[i], delPartA_1[i]);
if (kbhit())
break;
for (i = 0; PartA_2[i] != 0; i++)
tm_sound(PartA_2[i], delPartA_2[i]);
if (kbhit())
break;
for (i = 0; PartB_1[i] != 0; i++)
tm_sound(PartB_1[i], delPartB_1[i]);
if (kbhit())
break;
for (i = 0; PartB_2[i] != 0; i++)
tm_sound(PartB_2[i], delPartB_2[i]);
if (kbhit())
break;
for (i = 0; PartC_1[i] != 0; i++)
tm_sound(PartC_1[i], delPartC_1[i]);
if (kbhit())
break;
for (i = 0; PartC_2[i] != 0; i++)
tm_sound(PartC_2[i], delPartC_2[i]);
if (kbhit())
break;
for (i = 0; PartD[i] != 0; i++)
tm_sound(PartD[i], delPartD[i]);
} while (ch!=27);
break;
case 72: //up
if (y > 1)
y--;
else if (y == 1)
{
sound(100);
delay(100);
nosound();
y = 11;
}
break;
case 80: //down
if (y <= 10)
y++;
else if (y > 10)
{
sound(100);
delay(100);
nosound();
y = 1;
}
break;
case 77: //right
if (x <= 30)
x++;
else if (x > 30)
{
sound(100);
delay(100);
nosound();
x = 1;
}
break;
case 75: //left
if (x > 1)
x--;
else if (x == 1)
{
sound(100);
delay(100);
nosound();
x = 31;
}
break;
default: break;
}
} while (ch != 27);
return 0;
}
int getkey()
{
union REGS regs;
regs.h.ah = 0x07;
int86(0x21, ®s, ®s);
return regs.h.al;
}
void tm_sound(int freq, int time)
{
int cnt;
// Задаем режим канала 2 таймера
outp(0x43, 0xb6);
// Вычисляем задержку для загрузки в
// регистр счетчика таймера
cnt = (int)(1193180L / freq);
// Загружаем регистр счетчика таймера - сначала
// младший, затем старший байты
outp(0x42, cnt & 0x00ff);
outp(0x42, (cnt & 0xff00) >> 8);
// Включаем громкоговоритель. Сигнал от
// канала 2 таймера теперь будет проходить
// на вход громкоговорителя
outp(0x61, inp(0x61) | 3);
// Выполняем задержку.
delay(time);
// Выключаем громкоговоритель.
outp(0x61, inp(0x61) & 0xfc);
}
Примеры запуска программы
Вывод
В ходе выполнения данной лабораторной работы была изучена работа с клавиатурой: ознакомились со стандартными средствами библиотеки C++ и средствами системы прерываний DOS и BIOS, обслуживающими клавиатуру.
Структурная схема аппаратных средств, используемых при выполнении программы с необходимой степенью детализации содержимого блоков.