Файл: jourdain_spravochnik_programmista.docx

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 04.07.2020

Просмотров: 3139

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

щие:

Регистр A: бит 7 1 = идет модификация времени (надо ждать

значения 0, чтобы читать)

Регистр B: бит 6 1 = разрешено периодическое прерывание

бит 5 1 = разрешено прерывание тревоги

бит 4 1 = разрешено прерывание конца модификации

бит 1 1 = часы считаются до 24, 0 = до 12

бит 0 1 = разрешено запоминание времени суток



Часы реального времени на AT могут вызывать аппаратное преры-

вание IRQ8. Программа может установить вектор этого прерывания на

любую процедуру, которую требуется выполнить в определенное время

[1.2.3]. Используйте вектор 4AH. Операции в реальном времени,

производимые таким образом, менее хлопотны, чем обсуждаемые в

[2.1.7] (хотя и ценой компактности программ). Прерывание может

вызываться одним из трех способов, каждый из которых запрещен при

старте. Периодическое прерывание происходит через определенные

интервалы времени. Периодичность приближенно равна одной милли-

секунде. Прерывание тревоги происходит когда значение трех ре-

гистров тревоги совпадает со значениями соответствующих временных

регистров. Прерывание конца модификации происходит после каждого

обновления значений регистров микросхемы.

Прерывание 1AH расширено в BIOS AT, чтобы оно позволяло читать

и устанавливать часы реального времени. Поскольку показания ни-

когда не состоят более чем их двух десятичных цифр, то значения

времени выдаются в двоично-кодированной десятичной форме (BCD),

когда байт делится на две половины и каждая десятичная цифра

представляется четырьмя битами. Такой формат позволяет легко

переводить числа в форму ASCII. Программе нужно только сдвинуть

половину байта в младший конец регистра и добавить 48 для получе-

ния кода ASCII, соответствующего данному числу. Для всех IBM PC

функции 0 и 1 прерывания 1AH читают и устанавливают счетчик вре-

мени суток BIOS. Для часов реального времени AT имеется шесть

новых функций:


Функция 2: Чтение времени из часов реального времени

При возврате: CH = часы в BCD

CL = минуты в BCD

DH = секунды в BCD

Функция 3: Установка времени часов реального времени

При входе: CH = часы в BCD

CL = минуты в BCD

DH = секунды в BCD

DL = if daylight savings, else 1

Функция 4: Чтение даты из часов реального времени

При возврате: CH = век в BCD (19 или 20)

CL = год в BCD (с 1980)

DH = месяц в BCD

DL = день месяца в BCD

Функция 5: Установка даты часов реального времени

При входе: CH = век в BCD (19 или 20)

CL = год в BCD (с 1980)

DH = месяц в BCD

DL = день месяца в BCD

Функция 6: Установка тревоги для часов реального времени

При входе: CH = часы в BCD

CL = минуты в BCD

DH = секунды в BCD

Функция 7: Сброс тревоги (нет входных регистров)



Тревога устанавливается как смещение, относительно текущего мо-

мента времени. Максимальный период равен 23:59:59. Как уже гово-

рилось выше, вектор прерывания 4AH должен указывать на процедуру

обработки тревоги. Отметим, что если часы не работают (наиболее

вероятно, из-за отсутствия питания), то выполнение функций 2, 4 и

6 устанавливает флаг переноса.




2.1.5 Задержка программных операций.




Если Вы осуществляете задержку в программе посредством пустого

цикла, то Вам может потребоваться много времени для того, чтобы

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

буемую длительность, то нельзя быть уверенным, что Ваша программа

будет давать нужное время задержки при всех условиях. Длитель-

ность цикла может меняться в зависимости от используемого компи-

лятора (или, для Бейсика, от того, компилируется программа или

нет). А в наше время, когда имеется большой набор машин совмести-

мых с IBM PC - имеющих широкий диапазон скорости процессора -

даже цикл на языке ассемблера может приводить к различным време-

нам задержки. Поэтому разумно определять время программной за-

держки непосредственно по часам. Частота отсчета 18.2 раза в

секунду, используемая для модификации счетчика времени суток,

должна вполне удовлетворять большинство потребностей (как увели-

чить частоту отсчетов см. [2.1.1]).

Чтобы обеспечить задержку данной продолжительности, программа

должна подсчитать требуемое число импульсов счетчика времени

суток. Это значение добавляется к считанному текущему значению

счетчика. Затем программа постоянно считывает значение счетчика и

сравнивает его с запомненным. Когда достигается равенство, то

требуемая задержка прошла и можно продолжать выполнение програм-

мы. Четыре байта, в которых хранится значение счетчика времени

суток хранятся, начиная с адреса 0040:006C (как обычно, начиная с

младшего байта). Для задержек меньших 14 секунд можно пользовать-

ся только младшим байтом. Два младших байта позволяют задержки до

одного часа (точнее, на пол-секунды меньше, чем час).


Высокий уровень.


В Бейсике можно использовать оператор SOUND [2.2.2] со значе-

нием частоты, равным 32767. В этом случае звук не будет генериро-

ваться вообще. Это отсутствие звука будет длиться столько отсче-

тов времени суток, сколько Вы укажете. Для 5-секундной задержки

нужен 91 отсчет (5 * 18.2). Поэтому


100 SOUND 32767,91 'останавливает программу на 5 секунд


Для прямого чтения счетчика времени суток нужно:


100 DEF SEG = 0 'установка сегмента на начало памяти

110 LOWBYTE = PEEK(&H46C) 'получение младшего байта

120 NEXTBYTE = PEEK(&H46D) 'получение следующего байта

130 LOWCOUNT = NEXTBYTE*256 + LOWBYTE 'значение двух байтов


Средний уровень.


Прочитайте значение счетчика времени суток BIOS, используя

функцию 0 прерывания 1AH и добавьте к нему необходимое число

импульсов по 1/18 секунды. После этого считывайте текущие значе-


ния счетчика времени суток, постоянно сравнивая с требуемой вели-

чиной. При достижении равенства надо кончать задержку. Прерывание

1AH возвращает два младших байта в DX (большинство задержек укла-



дываются в этих пределах), поэтому два старших байта, возвращае-

мые в CX, могут игнорироваться, что позволит Вам избежать

32-байтных операций. В данном примере установлена задержка на 5

секунд, что соответствует 91 отсчету.


;---получение значения счетчика и установка задержки

MOV AH,0 ;номер функции для "чтения"

INT 1AH ;получаем значение счетчика

ADD DX,91 ;добавляем 5 сек. к младшему слову

MOV BX,DX ;запоминаем требуемое значение в BX

;---постоянная проверка значения счетчика времени суток BIOS

REPEAT: INT 1AH ;получаем значение счетчика

CMP DX,BX ;сравниваем с искомым

JNE REPEAT ;если неравен, то повторяем снова

;иначе, задержка окончена


AT имеет добавочную функцию прерывания 15H, которая позволяет

осуществить задержку на указанное время. Поместите 86H в AH, а

число микросекунд задержки в CX:DX. После этого выполните преры-

вание.




2.1.6 Операции запрограммированные во времени.




Программа определяет время для выполнения определенной опера-

ции в точности так же, как и человек: берется начальное показание

счетчика времени суток и затем сравнивается с последующими пока-

заниями. Можно получать значения в формате часы-минуты-секунды,

но слишком хлопотно вычислять разницу между такими показаниями,

поскольку система счета не десятичная. Лучше прямо читать счетчик

времени суток BIOS, измерять продолжительность в 1/18 секунды, а

затем уже переводить ее в обычный формат чч:мм:сс.


100 GOSUB 500 'получаем значение счетчика

110 START = TOTAL 'сохраняем начальное значение в START

.

(далее идет процесс, длительность которого измеряется)

.

300 GOSUB 500 'получаем финальное значение

310 TOTAL = TOTAL - START 'подсчитываем число импульсов

320 HOURS = FIX(TOTAL/65520) 'вычисляем число часов

330 TOTAL = TOTAL - HOURS*65520 'вычитаем часы из TOTAL

340 MINUTES = FIX(TOTAL/1092) 'вычисляем число минут

350 TOTAL = TOTAL - MINUTES*1092 'вычитаем минуты из TOTAL

360 SECONDS = FIX(TOTAL/18.2) 'вычисляем число секунд

370 PRINT HOURS,MINUTES,SECONDS 'печатаем результат

380 END

.

.

500 DEF SEG = 0 'подпрограмма чтения времени суток

510 A = PEEK(&H46C) 'получаем младший байт

520 A = PEEK(&H46D) 'получаем следующий байт

530 A = PEEK(&H46E) 'и еще один

540 TOTAL = A + B*256 + C*65535 'подсчитываем результат в TOTAL

550 RETURN 'все сделано


Функция TIMER в Бейсике возвращает число секунд, прошедших с

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

в 0. Обычно это число секунд, прошедших со времени последнего

включения компьютера. Если при старте системы правильно было

установлено системное время, то TIMER возвращает число секунд,

прошедших с полуночи. Просто напишите N = TIMER.


Средний уровень.


Прерывание 1AH имеет две функции для установки (AH = 1) и


получения (AH = 0) счетчика времени суток. Для чтения счетчика

надо просто выполнить прерывание с AH = 0. При возврате значение

счетчика содержится в CX:DX, причем младшее слово в CX. AL содер-

жит 0, если счетчик не переходил через границу 24 часов с момента

последней установки. Для установки счетчика поместите два слова в

те же регистры, а в AH - 1. В приведенном примере измеряются

промежутки времени в пределах часа. При этом нужны только два

младших байта счетчика. Но в этом случае необходимо проверять,

что не было перехода через границу, когда начальное значение было

больше, чем следующее.



;---в сегменте данных

OLDCOUNT DW 0 ;храним начальное значение счетчика

;---получаем начальное значение счетчика

MOV AH,0 ;номер функции

INT 1AH ;получаем значение счетчика

MOV OLDCOUNT,DX ;сохраняем начальное значение

.

(здесь идет процесс, длительность которого измеряется)

.

;---позднее вычисляем длительность процесса

MOV AH,0 ;номер функции

INT 1AH ;получаем значение счетчика

MOV BX,OLDCOUNT ;считываем старое значение

CMP BX,DX ;проверяем на переполнение

JG ADJUST ;обработка переполнения

SUB DX,BX ;иначе берем разность

JMP SHORT FIGURE_TIME ;и переводим ее в обычный вид

;---обработка переполнения

ADJUST: MOV CX,0FFFFH ;помещаем в CX максимальное число

SUB CX,BX ;вычитаем первое значение

ADD CX,DX ;добавляем второе значение

MOV DX,CX ;результат храним в DX

;---процедура перевода времени в обычный формат

FIGURE_TIME: ;делим на 18.2 секунды и т.д.




2.1.7 Управление работой в реальном времени.




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

ции в указанный момент времени, а не при первой возможности.

Такого рода операции обычно ассоциируются с роботехникой, но

имеется множество других приложений. Имеется выбор подхода к

операциям в реальном времени. Для программ, которые не должны

ничего делать в промежутке между инструкциями, требующими времен-

ной привязки, можно просто периодически проверять счетчик времени

суток, ожидая наступления нужного момента. Такой подход практи-

чески сводится к набору пустых циклов, описанных в [2.1.5].

Второй подход более сложен. Он используется, когда программа

постоянно занята какой-либо работой, но она должна в определенные

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

ной задачи. В этом случае расширяют прерывание таймера, которое

выполняется 18.2 раза в секунду. Когда это прерывание происходит,

дополнительный код проверяет новое значение счетчика времени

суток и если наступил определенный момент времени, запускает

нужную процедуру. Этот процесс показан на рис. 2-3. Приведенные

здесь простые примеры показывают, как создать в своей программе

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


вой сигнал, когда подошло время. (Более сложный пример низкого

уровня в [2.2.6] исполняет музыку, в то время когда процессор

занят другими делами.)


Высокий уровень.


Бейсик обеспечивает примитивный контроль над операциями в

реальном времени посредством оператора ON TIMER(n) GOSUB. Когда

программа встречает этот оператор, то она начинает отсчитывать n

секунд. Тем временем выполнение программы продолжается. Когда n

секунд прошло, то программа переходит на подпрограмму, начинаю-

щуюся с указанного номера строки, выполняет ее и возвращает уп-

равление на то место, откуда была вызвана подпрограмма. После

этого отсчет снова начинается с нуля и подпрограмма будет вызвана

снова еще через n секунд.

ON TIMER не будет функционировать, до тех пор пока он не раз-

решен оператором TIMER ON. Оператор TIMER OFF запрещает его рабо-

ту. В тех случаях, когда отсчет времени должен продолжаться, но

переход на подпрограмму должен быть задержан, надо использовать

оператор TIMER STOP. В этом случае отмечается, что n секунд прош-

ло, но переход на подпрограмму будет выполенен только после того,

как встретится оператор TIMER ON.

Поскольку он повторяется, оператор ON TIMER особенно полезен

для вывода на экран текущего времени:


100 ON TIMER(60) GOSUB 500 'меняем показания часов каждые 60

110 TIMER ON 'секунд и разрешаем работу таймера

.

.

500 LOCATE 1,35:PRINT "TIME: ";LEFT$(TIME$,5) 'позиционируем

510 RETURN 'курсор и печатаем время



Низкий уровень.


BIOS содержит специальное пустое прерывание (1CH), которое

ничего не делает, пока Вы не напишите для него процедуру. При

старте вектор этого прерывания указывает на инструкцию IRET

(возврат из прерывания); при его вызове происходит моментальный

возврат. Но прерывание 1CH интересно тем, что оно вызывается

прерыванием таймера BIOS после того, как это прерывание обновило

значение счетчика времени суток. Можно сказать, что это аппарат-

ное прерывание, происходящее автоматически 18.2 раза в секунду.

Вы можете изменить вектор этого прерывания так, чтобы он указывал

на процедуру в Вашей программе. После этого Ваша процедура будет

вызываться 18.2 раза в секунду. О том как написать и установить

свою процедуру обработки прерывания см. в [1.2.3].

Написанная Вами процедура должна прочитать только что модифи-

цированное значение счетчика времени суток, сравнить его с ожи-

даемым временем, и выполнить то что требуется, когда ожидаемое

время наконец наступит. Естественно, что когда время еще не по-

дошло, то процедура просто возвращает управление, ничего не де-

лая. Таким образом, процессор не выполняет лишней работы.

В приведенном примере процедура (не показанная здесь) запраши-

вает у пользователя число минут (до 60), которое должно пройти до

того, как раздастся звонок будильника. Это число, запасенное в

MINUTES, умножается на 1092 для перевода в эквивалентное число