Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Лабораторная работа № 9-10.  «Изучение функций системного таймера». Краткие теоретические и учебно-методические материалы




Лабораторная работа № 9-10

 «Изучение функций системного таймера»

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

Образовательные результаты, заявленные во ФГОС третьего поколения:

Студент должен

уметь:

- осуществлять разработку кода программного модуля на современных языках программирования;

- создавать программу по разработанному алгоритму как отдельный модуль;

- выполнять отладку и тестирование программы на уровне модуля

знать:

- основные этапы разработки программного обеспечения;

- основные принципы технологии структурного и объектно-ориентированного программирования;

- основные принципы отладки итестирования программных продуктов.

Краткие теоретические и учебно-методические материалы

по теме лабораторной работы

Микросхема таймера генерирует импульсы частоты 1193180 гц. Эта последовательность импульсов поступает на три канала таймера. В каждом канале есть свой счетчик, работающий как делитель частоты, максимальное число которое может быть записано в счетчике (коэффициент деления) - 655357. Счетчики каналов таймера независимы друг от друга и доступны для программиста. Назначение каналов таймера следующее:

· канал 0 используется для системной службы времени. При инициализации системы BIOS записывает в счетчик этого канала максимально возможное число, таким образом, импульсы на выходе делителя выдаются с частотой около 18. 2 гц (период этой частоты - около 55 мсек - программисты иногда называют " тиком" таймера). Выход делителя этого канала поступает на контроллер прерываний и вызывает прерывание с номером 8;

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

· выход канала 2 поступает на динамик ПЭВМ, этот канал используется для генерации звука.

Каждый канал может работать в одном из 6 режимов, но программисты, как правило, используют его в режиме 3 (генератор меандра).

Программирование канала таймера представляет собой запись числа в счетчик канала. Имеется один управляющий порт - 0x43 для всех каналов и по одному порту данных для каждого канала - 0x40, 0x41, 0x42. При программировании следует записать в порт 0x43 управляющий байт, который обычно имеет вид:  x x 1 1 0 1 1 0, где xx - номер канала таймера, а затем послать в порт данных выбранного канала сначала младший, а затем старший байт счетчика.

 

Пример:         

Дана функция - y=50*(sin(x/10)+cos(x/8))+R+150;

R - в диапазоне 0 - 10;

частота - 36. 4 Гц.

Программа состоит из основной программы и трех функций.

void *readvect(int in) - функция читает вектор прерывания с номером in и возвращает его значение.

void writevect (int in, void *h) - функция устанавливает новый вектор прерывания in на новый обработчик этого прерывания по адресу h.

void interrupt newtime() - процедура нового обработчика прерывания таймера.

В этой программе применяются две константы:

TIMEINT=8 - номер прерывания таймера;

NN=100 - максимальное число показаний АЦП.

Переменные, глобальные для всей программы:

y - массив показаний АЦП;

ny - текущий индекс в массиве показаний;

yc - текущее значение функции;

kf - счетчик вызовов oldtime (oldtime вызывается каждые второй раз);

rr и sr - переменные, которые используются для задания значений регистров общего назначения и сегментных регистров, соответственно при вызове прерывания.

Переменные главной программы:

oldtic - старый коэффициент деления;

newtic - новый коэффициент деления (применяется для увеличения частоты вызова прерываний таймера);

x - аргумент заданной функции F(x);

dd - тип графического адаптера;

m - режим графики;

errorcode - код результата инициализации графики.

Главная программа постоянно вычисляет значения заданной функции F(x) при переменном аргументе, что имитирует непрерывный сигнал, а обработчик прерывания 8 имитирует преобразователь с постоянным шагом дискретизации по времени. Перед началом работы канал 0 таймера программируется на частоту в 2 рази большую обычной (записью в порт 43h управляющего байта 00110110b=36h, а потом посылкой в порт 40h нового значения коэффициента деления), таким образом, " частота дискретизации" составляет около 36. 4 Гц. При поступлении следующего прерывания запоминается текущее значение функции F(x), старый обработчик прерывания oldtime вызывается не при кожному прерывании, а лишь один раз из двух (переменная kf - счетчик по модулю 2), когда oldtime не вызывается, наш обработчик сам сбрасывает контроллер прерываний посылкой значения 20h в порт 20h. После набора 100 " показаний АЦП" восстанавливается старый вектор обработчика таймера, а результат аналого-цифрового преобразование выводится на терминал в графическом режиме в виде решетчатой функции.

Функция readvect() читает вектор заданного прерывания. Для чтения вектора применяется функция 35h DOS (прерывания 21h):

Вход: AH = 35h;

AL = номер вектора прерывания.

Выход:       ES: BX = адрес программы обработки прерывания.

Функция writevect() устанавливает новый вектор прерывания по заданному адресу. Для записи вектора применяется функция 25h DOS:

Вход: AH = 25h;

AL = номер вектора прерывания;

DS: BX = 4-байтный адрес нового обработчика прерывания.

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

#include < dos. h>

#include < math. h>

#include < stdlib. h>

#include < graphics. h>

#include < time. h>

#include < conio. h>

#define TIMEINT 8      /* Прерывание таймера */

#define NN 100 /* Максимальное количество показаний */

 

void interrupt (*oldtime)(); /* Новый обpаботчик */

                        /* пpеpываний таймеpа */

 

void interrupt newtime(); /* Старый обpаботчик */

                        /* пpеpываний таймеpа */

static int y[NN]; /* Накопитель показаний     */

static int ny; /* Индекс в массиве y       */

static int yc; /* Текущее значение         */

static int kf; /* Счетчик вызовов oldtime  */

union REGS rr; /* Запись нового вектора    */

struct SREGS sr;

void *readvect(int in); /* Получение старого вектора */

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

/*--------------------------------------------------------*/

void main()

{

unsigned oldtic=65535u; /* Старый коэфф. деления */

unsigned newtic=32768u; /* Новый коэфф. деления  */

int dd,              /* Графический драйвер   */

m,               /* Графический режим     */

errorcode;       /* Код ошибки            */

double x;            /* Аргумент функций sin и cos */

textbackground(0);

clrscr();

textattr(0x0a);

cprintf("          Лабораторная работа N6         " );

cprintf(" \n           Управление таймером          " );

textattr(0x8e);

gotoxy(35, 12);

cprintf(" Please wait" );

/* Программирование канала 0 */

outportb(0x43, 0x36);               /* Управляющий байт */

outportb(0x40, newtic& 0x00ff); /* Младший байт счетчика */

outportb(0x40, newtic> > 8); /* Старший байт счетчика */

ny=-1;        /* Признак того, что АЦП еще не началось */

kf=15;

/* Подключение к вектору */

oldtime=readvect(TIMEINT);

writevect(TIMEINT, newtime);

/* Запуск " непрерывного процесса" */

randomize();

for (x=ny=0; ny< NN; x+=1)

yc=(int)(50*(sin(x/10)+cos(x/8))+random(11)+150);

/* Восстановление вектора */

writevect(TIMEINT, oldtime);

/* Восстановление канала 0 */

outportb(0x43, 0x36);               /* Управляющий байт */

outportb(0x40, oldtic& 0x00ff); /* Младший байт счетчика */

outportb(0x40, oldtic> > 8); /* Старший байт счетчика */

/* Вывод запомненных результатов */

dd=3; /* EGA, 16 цветов */

m=1; /* Режим 640*350 */

initgraph(& dd, & m, " " );

/* проверка результата инициализации */

errorcode = graphresult();

if (errorcode! = grOk)  /* ошибка графического режима */

{

printf(" Graphics error: %s\n", grapherrormsg(errorcode));

printf(" Press any key to halt: " );

getch();

exit(1);                     /* аварийное завершение */}

setcolor(10);

settextstyle(0, 0, 2);

outtextxy(15, 10, " Результати аналого-цифрового преобразования: " );

setcolor(9);

  rectangle(15, 40, 624, 330);

setcolor(11);

for(ny=0; ny< NN; ny++)

{

circle(22+ny*6, 330-y[ny]*1, 2);

line(22+ny*6, 330, 22+ny*6, 330-y[ny]*1); }

setcolor(12);

settextstyle(0, 0, 1);

outtextxy(260, 340, " Нажмите любую клавишу... " );

getch();

closegraph();

}

 

/* Новый обpаботчик пpеpиваний таймеpа */

void interrupt newtime()

{

if (--kf< 0) {

/* Виклик oldtime - на 2-й раз */

(*oldtime)();

kf=1; }

else /* иначе - сброс контроллера */

outportb(0x20, 0x20);

if ((ny> =0)                  /* Если АЦП началось, */

& & (ny< NN)) /* и NN показаний еще не набрано, */

y[ny++]=yc;    /* запоминание очередного показания *}

/* Получение старого вектора */

void *readvect(int in)

{

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);

}

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

 

Задания для лабораторной работы:

Таблица 1 – варианты индивидуальных заданий

№ варианта R y=F(x) Частота (ГЦ)
0 - 10 y=((100-x)%100)*0. 5+R+100 72. 7
0 - 10 y=((77-x)%200)*0. 1+R+150 145. 5
0 - 10 y=40*(cos(x/10)+cos(x/6))+R+100 36. 4
0 - 2 y=50*(cos(x/10)+R*cos(x/5))+150 54. 5
0 - 2 y=50*sin(cos(x/10)+R)+150 90. 9
0 - 1 y=0. 5*(x%100)+100*sin(x/5)*R+150 72. 7
0 - 1 y=0. 5*(x%100)+50*sin(x/50)*(R+1)+150 145. 5
0 - 1 y=50*sin(x/(10+R))+150 36. 4
0 - 0. 2 y=50*(fabs(sin(x/10))+R)+150 54. 5
0 - 10 y=10*-1N*(x/100)+R+150 90. 9
0 - 10 y=-1N*50*sin(x/10)+150+R 72. 7
0 - 10 y=0. 5*-1N*(x%200)*sin(x/10)+150+R 145. 5
0 - 10 y=0. 5*-1N*(x%200)+50*sin(x/10)+150+R 36. 4
0 - 10 y=50*(sin(x/64)+sin(x/32)+ +0. 1*sin(x/4)+0. 1*sin(x/2))+R+150 54. 5
0 - 10 y=50*(sin(x/64)+sin(x/32)+ +sin(x/2))+R+150 90. 9
0 - 10 y=0. 5*(x%100+-1N*x%200)+150+R 72. 7
0 - 10 y=0. 5*(-1N*x%100+x%200)+R+150 145. 5
0 - 0. 1 y=0. 5*(-1N*x%100+200*R*sin(x/10))+150 36. 4
0 - 0. 3 y=50*(fabs(sin(x/10))+R)+150 55. 5
0 - 10 y=10*-1N*(x/100)+R+150 93. 9
0 - 10 y=-1N*50*sin(x/10)+50+R 75. 7
0 - 10 y=0. 5*-1N*(x%200)*sin(x/10)+150+R 145. 5
0 - 10 y=0. 5*-1N*(x%200)+50*sin(x/10)+150+R 36. 4
0 - 10 y=50*(sin(x/64)+sin(x/32)+ +0. 1*sin(x/4)+0. 1*sin(x/2))+R+150 54. 5
0 - 10 y=50*(sin(x/64)+sin(x/32)+ +sin(x/2))+R+150 90. 9
0 - 10 y=0. 5*(x%100+-1N*x%200)+50+R 75. 7
0 - 10 y=0. 5*(-1N*x%100+x%200)+R+50 135. 5
0 - 0. 3 y=0. 5*(-1N*x%100+200*R*sin(x/10))+150 39. 4
0 - 10 y=((77-x)%200)*0. 1+R+150 145. 5
0 - 10 y=50*(cos(x/10)+cos(x/6))+R+100 39. 4
0 - 2 y=50*(cos(x/10)+R*cos(x/5))+150 58. 5
0 - 2 y=50*sin(cos(x/10)+R)+150 91. 9
0 - 1 y=0. 5*(x%100)+100*sin(x/5)*R+5 75. 7
0 - 1 y=0. 5*(x%100)+50*sin(x/50)*(R+1)+50 155. 5
0 - 1 y=50*sin(x/(10+R))+50 39. 4

Построить модель аналого-цифрового преобразователя (АЦП), которая работает в реальном времени. Процесс, который дискретизуется, моделируется программой (программным блоком), который выполняет циклическое вычисление функции y=F(x), где x - номер итерации. Преобразователь моделируется программой, которая выполняет с заданной частотой (в реальном времени) прерывание процесса, считывание и запоминание текущего значения функции. Запомнить не меньше 80 значений функции. Обеспечить наглядное представление результатов работы " АЦП".

Примечание: R - случайное вещественное число из последовательности, равномерно распределенной в указанном интервале.

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

1. Назовите функции таймера.

2. Назовите назначение каналов таймера.

3. Что представляет собой программирование канала таймера.

4. Какаим образом происходит доступ к счетчику времени.

5. Какой частоты таймер генерирует импульсы?

 

 

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...