2392_Смирнова_ЛР5_ЭВМ
.docxМИНОБРНАУКИ РОССИИ
Санкт-Петербургский государственный
электротехнический университет
«ЛЭТИ» им. В.И. Ульянова (Ленина)
Кафедра ВТ
отчет
по лабораторной работе №5
по дисциплине «Организация ЭВМ и систем»
Тема: Использование аппаратных прерываний, прерывание таймера
Студент гр. 2392 |
|
Смирнова М. В. |
Преподаватель |
|
Ельчанинов М. Н. |
Санкт-Петербург
2023
Цель работы.
Цель работы – знакомство с различного вида аппаратными прерываниями и создание собственных подпрограмм обработки прерываний.
Задание на лабораторную работу.
Целью лабораторной работы является разработка алгоритма и реализация программы подключения собственной подпрограммы обработки прерывания и использование её в цепочке со стандартной подпрограммой обработки прерывания от одного из следующих устройств компьютера:
системный таймер;
клавиатура;
контроллер накопителя на гибких магнитных дисках;
таймер реального времени;
контроллер накопителя на жёстком магнитном диске.
Б лок-схема
Текст программы
#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);
}
Примеры запуска программы
Структурная схема аппаратных средств, используемых при выполнении программы с необходимой степенью детализации содержимого блоков.
Вектор прерывания системного
таймера
ОЗУ (RAM)
………..
Таблица векторов прерываний (1024
байт)
0000:0000
0000:0008
IRQ0
………..
0000:03FF
………..
………..
ПЗУ (RОM)
Контроллер
ИП
Монитор
Контроллер
ЦП (CPU)
СИСТЕМНАЯ ШИНА
Клавиатура
Контроллер
Таблица векторов прерываний занимает первый килобайт оперативной памяти — адреса от 0000:0000 до 0000:03FF. Таблица состоит из 256 элементов — FAR-адресов обработчиков прерываний. Эти элементы называются векторами прерываний. В первом слове элемента таблицы записано смещение, а во втором — адрес сегмента обработчика прерывания. Векторами являются просто полные адреса памяти программы (в сегментированной форме), которая должна быть активизирована в случае возникновения прерывания.
Прерывание с номером 8 — IRQ0 — прерывание интервального таймера, возникает 18,2 раза в секунду.