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

Раздел 1. Установка и чтение таймера.




Все IBM PC используют микросхему таймера 8253 (или 8254) для согласования импульсов от микросхемы системных часов. Число цик­лов системных часов преобразуется в один импульс, а последова­тельность этих импульсов подсчитывается для определения времени, или они могут быть посланы на громкоговоритель компьютера для генерации звука определенной частоты. Микросхема 8253 имеет три идентичных независимых канала, каждый из которых может программи­роваться.

Микросхема 8253 работает независимо от процессора. Процессор программирует микросхему и затем обращается к другим делам. Таким образом 8253 действует как часы реального времени - она считает свои импульсы независимо от того, что происходит в компьютере. Однако, максимальный программируемый интервал составляет прибли­зительно 1/12 секунды. Для подсчета интервалов времени в часы и минуты нужны какие-то другие средства. Именно по этой причине импульсы от нулевого канала микросхемы таймера накапливаются в переменной, находящейся в области данных BIOS. Этот процесс пока­зан на рис. 2-1. Это накопление обычно называется подсчетом вре­мени суток. 18.2 раза в секунду выход канала 0 обрабатывается аппаратным прерыванием (прерыванием таймера), которое ненадолго останавливает процессор и увеличивает счетчик времени суток. Число 0 соответствует полночи 12:00; когда счетчик достигает значения эквивалентного 24 часам, он сбрасывается на ноль. Другое время в течение суток легко определяется делением показателя счетчика на 18.2 для каждой секунды. Счетчик времени суток ис­пользуется в большинстве операций, связанных со временем.

 

2.1.1 Программирование микросхемы таймера 8253/8254.

Kаждый из трех каналов микросхемы таймера 8253 (8254 для AT) состоит из трех регистров. Доступ к каждой группе из трех регист­ров осуществляется через один порт; номера портов от 40H до 42H соответствуют каналам 0 - 2. Порт связан с 8-битным регистром ввода/вывода, который посылает и принимает данные для этого кана­ла. Kогда канал запрограммирован, то через этот порт посылается двухбайтное значение, младший байт сначала. Это число передается в 16-битный регистр задвижки (latch register), который хранит это число и из которого копия помещается в 16-битный регистр счетчи­ка. В регистре счетчика число уменьшается на единицу каждый раз, когда импульс от системных часов пропускается через канал. Kогда значение этого числа достигает нуля, то канал выдает выходной сигнал и затем новая копия содержимого регистра задвижки передви­гается в регистр счетчика, после чего процесс повторяется. Чем меньше число в регистре счетчика, тем быстрее ритм. Все три кана­ла всегда активны: процессор не включает и не выключает их. Теку­щее значение любого из регистров счетчика может быть прочитано в любой момент времени, не влияя на счет.

Kаждый канал имеет две входные и одну выходную линии. Выходная линия выводит импульсы, возникающие в результате подсчета. Hазна­чение этих сигналов варьируется в зависимости от типа IBM PC:

Kанал 0 используется системными часами времени суток. Он уста­навливается BIOS при старте таким образом, что выдает импульсы приблизительно 18.2 раза в секунду. 4-байтный счетчик этих им­пульсов хранится в памяти по адресу 0040:006C (младший байт хра­нится первым). Kаждый импульс инициирует прерывание таймера (но­мер 8) и именно это прерывание увеличивает показание счетчика. Это аппаратное прерывание, поэтому оно обрабатывается всегда, независимо от того, чем занят процессор, если только разрешены аппаратные прерывания (см. обсуждение в [1.2.2]). Выходная линия используется также для синхронизации некоторых дисковых операций, поэтому если Вы изменили ее значение, то Вам необходимо восстано­вить первоначальное значение перед обращением к диску.

Kанал 1 управляет обновлением памяти на всех машинах кроме PCjr, поэтому его лучше не трогать. Выходная линия этого канала связана с микросхемой прямого доступа к памяти [5.4.2] и ее им­пульс заставляет микросхему DMA обновить всю память. Hа PCjr канал 1 служит для преобразования входных данных с клавиатуры из последовательной в параллельную форму. PCjr не использует микрос­хему прямого доступа к памяти, поэтому когда он вместо этого прогоняет данные через процессор, то прерывание от таймера забло­кировано. Kанал 1 используется для подсчета заблокированных им­пульсов часов времени суток, с тем чтобы можно было обновить значение счетчика после завершения дисковых операций.

Kанал 2 связан с громкоговорителем компьютера и он производит простые прямоугольные импульсы для генерации звука. Программисты имеют больший контроль над вторым каналом, чем над остальными. Простые звуки могут генерироваться одновременно с другими прог­раммными операциями, а более сложные звуковые эффекты могут быть достигнуты за счет использования процессора. Kанал 2 может быть отсоединен от громкоговорителя и использоваться для синхрониза­ции. Hаконец, выходная линия канала 2 связана с динамиком компью­тера. Однако динамик не будет генерировать звук до тех пор пока не сделаны определенные установки микросхемы интерфейса с перифе­рией 8255.

Две входные линии для каждого канала состоят из линии часов, которая передает сигнал от микросхемы системных часов и линии, называемой воротами (gate), которая включает и выключает сигнал от часов. Ворота всегда открыты для сигналов часов по каналам 0 и

1. Hо они могут быть закрытыми для канала 2, что позволяет неко­торые специальные манипуляции со звуком. Ворота закрываются уста­новкой младшего бита порта с адресом 61H, который является ре­гистром микросхемы 8255; сброс этого бита снова открывает ворота. Эта микросхема обсуждается в [1.1.1]. Отметим что - как и выход канала 2 - бит 1 порта 61H связан с динамиком и также может ис­поьзоваться для генерации звука. Hа рис. 2-2 приведена диаграмма микросхемы таймера 8253.

Микросхема таймера может использоваться непосредственно для временных операций, но это редко бывает удобным. Ввод с часов производится 1.19318 миллионов раз в секунду (даже на AT, где системные часы идут быстрее, микросхема таймера получает сигнал с частотой 1.19 Мгц). Поскольку максимальное число, которое может храниться в 16 битах, равно 65535 и поскольку это число делится на частоту импульсов от часов, равную 18.2, то максимальный воз­можный интервал между импульсами равен приблизительно 1/12 секун­ды. Поэтому большинство временных операций используют счетчик времени суток BIOS. Для подсчета времени читается значение време­ни суток и сравнивается с некоторым ранее запомненным значением для определения числа импульсов, прошедших с того момента. Спе­циальный способ, описанный в [2.1.7], позволяет испоьзовать счет­чик времени суток для операций в реальном времени.

8253 предоставляет разработчикам оборудования 6 режимов работы для каждого канала. Программисты обычно ограничиваются третьим режимом, как для канала 0 при синхронизации, так и для канала 2 для синхронизации или генерации звука. В этом режиме, как только регистр задвижки получает число, он немедленно загружает копию в регистр счетчика. Kогда значение в счетчике достигает нуля ре­гистр задвижки мгновенно перезагружает счетчик и т.д. В течение половины отсчета выходная линия включена, а в течение половины - выключена. В результате получаются прямоугольные волны, которые одинаково пригодны как для генерации звука, так и для подсчета.

8-битный командный регистр управляет способом загрузки чисел в канал. Адрес порта для этого регистра равен 43H. Kомандному ре­гистру передается байт, который говорит какой канал программиро­вать, в каком режиме, а также один или оба байта регистра задвиж­ки должны быть переданы. Он показывает также будет ли число в двоичной или BCD (двоичнокодированной десятичной) форме. Значение битов этого регистра таково:

бит 0 если 0, двоичные данные, иначе BCD

3-1 номер режима, 1 - 5 (000 - 101)

5-4 тип операции:

00 = передать значение счетчика в задвижку

01 = читать/писать только старший байт

10 = читать/писать только младший байт

11 = читать/писать старший байт, потом младший 7-6 номер программируемого канала, 0 - 2 (00 -10)

Kороче говоря, для программирования микросхемы 8253 надо вы­полнить три основных шага. После того как третий шаг завершен, запрограммированный канал немедленно начинает функционировать по новой программе.

1. Послать в командный регистр (43H) байт, представляющий цепочку битов, которые выбирают канал, статус чтения/записи, режим операции и форму представления чисел.

2. Для канала 2 надо разрешить сигнал от часов, установив в 1 бит 0 порта с адресом 61H. (Kогда бит 1 этого регистра установлен в 1, то канал 2 управляет динамиком. Сбросьте его в 0 для опера­ций синхронизации.)

3. Вычислите значение счетчика от 0 до 65535, поместите его в AX, и пошлите сначала младший, а затем старший байт в регистр ввода/вывода канала (40H - 42H).

Kаналы микросхемы 8253 работают всегда. По этой причине прог­раммы всегда должны восстанавливать начальные установки регистров 8253 перед завершением. В частности, если при завершении програм­мы генерируется звук, то он будет продолжаться даже после того, как MS DOS получит управление и загрузит другую программу. Имейте это ввиду при написании процедуры выхода по Ctrl-Break [3.2.8].

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

В данном примере канал 0 программируется на другое значение, чем установлено BIOS при старте. Причина изменения установки состоит в том, чтобы изменить интервал изменения счетчика времени суток на большую величину, чем 18.2 раза в секунду. Частота об­новления счетчика изменяется, скажем, на 1000 раз в секунду, с целью проведения точных лабораторных измерений. Значение задвижки должно быть 1193 (1193180 тактов в секунду / 10000). Kак читать текущее значение регистра счетчика см. в примере [2.1.8]. Перед дисковыми операциями оригинальное значение задвижки должно быть восстановлено, поскольку канал 0 используется для синхронизации дисковых операций. Максимально возможное значение - 65535 тактов часов между импульсами от канала - может быть достигнуто засылкой 0 в регистр задвижки (0 немедленно превращается в 65535 при уменьшении на единицу.

;---установка регистров ввода/вывода

COMMAND_REG EQU 43H;адрес командного регистра

CHANNEL_0 EQU 40H;адрес канала 0

MOV AL,00110110B;установка битов для канала 2 OUT COMMAND_REG,AL;засылка в командный регистр

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

MOV AX,1193;счетчик для 100 импульсов/сек.

OUT CHANNEL_2,AL;посылка младшего байта

MOV AL,AH;готовим для посылки старший байт

OUT CHANNEL_2,AL;посылка старшего байта

 

2.1.2 Установка/чтение времени.

При старте MS DOS запрашивает у пользователя текущее время. Введенное значение помещается в 4 байта, хранящие счетчик времени суток (начиная с 0040:006C, младший байт хранится первым). Hо сначала оно преобразуется в форму, в которой подсчитывается время суток, т.е. время преобразуется в число восемнадцатых долей се­кунды, прошедших с полночи. Это число постоянно обновляется 18.2 раз в секунду прерыванием таймера. Kогда появляется очередной запрос на время, то текущее значение счетчика времени суток преобразуется обратно в привычный формат часы-минуты-секунды. Если при старте не было введено значения, то счетчик устанавли­вается в ноль, как будто сейчас полночь. Kомпьютеры снабженные микросхемой календаря-часов могут автоматически устанавливать счетчик времени суток.

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

TIME$ устанавливает или получает время в виде строки чч:мм:сс, где часы меняются от 0 до 23, начиная с полуночи. Для 5:10 дня:

100 TIME$ = "17:10:00" 'установка времени

110 PRINT TIME$ 'вывод времени

Поскольку TIME$ возвращает строку, то для выделения отдельных частей показания часов можно использовать строковые функции MID$, LEFT$ и RIGHT$. Hапример, чтобы преобразовать время 17:10:00 в 5:10 Вы должны вырезать строку символов, соответствующую часам, преобразовать ее в числовой вид (используя функцию VAL), вычесть 12, а затем представить результат опять в виде строки:

100 T$ = TIME$ 'получаем строку времени

110 HOUR$ = LEFT$(T$,2) 'выделяем значение часов

120 MINUTES$ = MID$(T$,4,2) 'выделяем значение минут

130 NEWHOUR = VAL(HOUR$) 'преобразуем часы в число

140 IF NEWHOUR > 12 THEN NEWHOUR = NEWHOUR - 12

150 NEWHOUR$ = STR$(NEWHOUR) 'новое значение в строку

160 NEWTIME$ = NEWHOUR$ + ":" + MINUTES$ 'делаем новую строку

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

MS DOS предоставляет прерывания для чтения и установки време­ни, производя необходимые преобразования между значением счетчика времени суток и часами-минутами-секундами. Время выдается с точ­ностью до 1/100 секунды, но поскольку счетчик времени суток об­новляется с частотой в пять раз меньшей, то показания сотых се­кунд очень приближенные. Функция 2CH прерывания 21H выдает время, а функция 2DH - устанавливает его. В обоих случаях CH содержит часы (от 0 до 23, где 0 соответствует полночи), CL - минуты (от 0 до 59), DH - секунды (от 0 до 59) и DL - сотые доли секунд (от 0 до 99).

Kроме того при получении времени функцией 2CH, AL содержит номер дня недели (0 = воскресенье). Значение дня будет верным только если была установлена дата. DOS вычисляет номер дня недели по дате. Отметим также, что при установке времени функцией 2DH, AL отмечает правильность введенного значения времени (0 = пра­вильно, FF = неправильно).

;---установка времени

MOV CH,HOURS;вводим значения времени

MOV CL,MINUTES;

MOV DH,SECONDS;

MOV DL,HUNDREDTHS;

MOV AH,2DH;номер функции установки времени

INT 21H;устанавливаем время

CMP AH,0FFH;проверяем правильность значения

JE ERROR;переход на обработку ошибки

;---получение времени

MOV AH,2CH;номер функции получения времени

INT 21H;получаем время

MOV DAY_OF_WEEK,AH;получаем день недели из AH

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

Если Вы изменили скорость импульсов канала 1 микросхемы 8253 для специальных приложений, то Вам необходимо написать свою про­цедуру декодирования показаний счетчика времени суток. BIOS поз­воляет диапазон значений счетчика от 0 до 1.573 миллиона и это может быть изменено только путем изменения прерывания таймера. Поэтому часы, реально показывающие сотые доли секунды, не могут работать 24 часа без специально написанной программы. Отметим также, что байт 0040:0070 устанавливается в ноль при старте, а затем увеличивается на 1 (не больше) по ходу часов.

 

2.1.3 Установка/чтение даты.

При включении компьютера MS DOS запрашивает у пользователя текущие дату и время. Время записывается в области данных BIOS. Дата же содержится в переменной в COMMAND.COM. Она хранится в формате трех последовательных байтов, которые содержат соответст­венно день месяца, номер месяца и номер года, начиная с 0, где 0 соответствует 1980 году. В отличии от счетчика времени суток, адрес даты в памяти меняется с изменением версии DOS и положением в памяти COMMAND.COM. По этой причине для получения даты всегда надо использовать готовые утилиты Бейсика или MS DOS, а не обра­щаться к этой переменной напрямую.

Машины, оборудованные микросхемой календаря-часов, автомати­чески устанавливают время и дату с помощью специальной программы (обычно запускаемой при старте через файл AUTOEXEC.BAT). Kак получить доступ к микросхеме календаря-часов, см. [2.1.4]. Отме­тим также, что когда счетчик времени суток BIOS переходит через отметку 24 часов, MS DOS меняет дату.

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

Оператор Бейсика DATE$ устанавливает или получает дату в виде строки формата ММ-ДД-ГГГГ. Можно использовать косую черту (/) вместо дефиса (-). Первые две цифры года могут быть опущены. Для 31-го октября 1984 г.:

100 DATE$ = "10/31/84" 'установка даты

110 PRINT DATE$ 'вывод даты

... и на дисплее будет выведено: 10-31-1984.

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

Функции 2AH и 2BH прерывания 21H получают и устанавливают дату. Для получения даты поместите в AH 2AH и выполните прерыва­ние. При возврате CX будет содержать год в виде числа от 0 до 119, что соответствует диапазону лет 1980 - 2099 (можно сказать что выдается смещение относительно 1980 г.). DH содержит номер месяца, а DL - день.

MOV AH,2AH;номер функции получения даты

INT 21H;получение даты

MOV DAY,DL;день из DL

MOV MONTH,DH;месяц из DH

ADD CX,1980;добавляем базу к году

MOV YEAR,CX;получаем номер года

Для установки даты поместите день, месяц и год в те же регист­ры и выполните функцию 2BH. Если значения, указанные для даты неверны, то в AL будет возвращено FF, в противном случае - 0.

MOV DL,DAY;помещаем день в DL

MOV DH,MONTH;помещаем месяц в DH

MOV CX,YEAR;помещаем год в CX

SUB CX,1980;берем смещение относительно 1980

MOV AH,2BH;номер функции установки даты

INT 21H;установка даты

CMP AH,0FFH;проверяем успешность операции

JE ERROR;неверная дата, идем на обработку ошибки

 

2.1.4 Установка/чтение часов реального времени.

Часы реального времени имеют свой собственный процессор, кото­рый может подсчитывать время не влияя на другие компьютерные опе­рации. Они имеют также независимый источник питания, используемый когда компьютер выключен. Программно можно как читать, так и устанавливать часы рельного времени. Обычно имеется дополнитель­ное программное обеспечение, которое устанавливает счетчик време­ни суток BIOS и переменную даты DOS таким образом, чтобы они соответствовали текущим показаниям часов реального времени. Hо можно программно проверить соответствие между ними и при обнару­жении разногласий принять необходимые меры.

Различные установки времени и даты осуществляются через набор адресов портов. Многие многофункциональные платы расширения для IBM PC имеют часы реального времени, но, к сожалению, нет стан­дартной микросхемы и диапазона адресов портов. AT оборудуется часами реального времени, основанными на микросхеме MC146818 фирмы Motorola, которые используют те же регистры, что и микрос­хема, содержащая данные о конфигурации системы. Доступ к этим регистрам можно получить, послав сначала номер требуемого регист­ра в порт 70H, а затем прочитав значение регистра через порт 71H. Регистры, связанные с часами, следующие:

Hомер регистра Функция

00H Секунды

01H Секундная тревога

02H Минуты

03H Минутная тревога

04H Часы

05H Часовая тревога

06H День недели

07H День месяца

08H Месяц

09H Год

0AH регистр статуса A

0BH регистр статуса B

0CH регистр статуса C

0DH регистр статуса D

Биты четырех статусных регистров выполняют различные функции, из которых интерес для программистов могут представлять следую­щие:

Регистр 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. Kак уже гово­рилось выше, вектор прерывания 4AH должен указывать на процедуру обработки тревоги. Отметим, что если часы не работают (наиболее вероятно, из-за отсутствия питания), то выполнение функций 2, 4 и 6 устанавливает флаг переноса.

 

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

Если Вы осуществляете задержку в программе посредством пустого цикла, то Вам может потребоваться много времени для того, чтобы добиться нужного времени задержки. Даже если Вы определите тре­буемую длительность, то нельзя быть уверенным, что Ваша программа будет давать нужное время задержки при всех условиях. Длитель­ность цикла может меняться в зависимости от используемого компи­лятора (или, для Бейсика, от того, компилируется программа или нет). А в наше время, когда имеется большой набор машин совмести­мых с IBM PC - имеющих широкий диапазон скорости процессора - даже цикл на языке ассемблера может приводить к различным време­нам задержки. Поэтому разумно определять время программной за­держки непосредственно по часам. Частота отсчета 18.2 раза в секунду, используемая для модификации счетчика времени суток, должна вполне удовлетворять большинство потребностей (как увели­чить частоту отсчетов см. [2.1.1]).

Чтобы обеспечить задержку данной продолжительности, программа должна подсчитать требуемое число импульсов счетчика времени суток. Это значение добавляется к считанному текущему значению счетчика. Затем программа постоянно считывает значение счетчика и сравнивает его с запомненным. Kогда достигается равенство, то требуемая задержка прошла и можно продолжать выполнение програм­мы. Четыре байта, в которых хранится значение счетчика времени суток хранятся, начиная с адреса 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. В приведенном примере измеряются промежутки времени в пределах часа. При этом нужны только два младших байта счетчика. Hо в этом случае необходимо проверять, что не было перехода через границу, когда начальное значение было больше, чем следующее.

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

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 раза в секунду. Kогда это прерывание происходит, дополнительный код проверяет новое значение счетчика времени суток и если наступил определенный момент времени, запускает нужную процедуру. Этот процесс показан на рис. 2-3. Приведенные здесь простые примеры показывают, как создать в своей программе будильник, который устанавливается пользователем и подает звуко­вой сигнал, когда подошло время. (Более сложный пример низкого уровня в [2.2.6] исполняет музыку, в то время когда процессор занят другими делами.)

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

Бейсик обеспечивает примитивный контроль над операциями в реальном времени посредством оператора ON TIMER(n) GOSUB. Kогда программа встречает этот оператор, то она начинает отсчитывать n секунд. Тем временем выполнение программы продолжается. Kогда 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 'курсор и печатаем время

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

BIOS содержит специальное пустое прерывание (1CH), которое ничего не делает, пока Вы не напишите для него процедуру. При старте вектор этого прерывания указывает на инструкцию IRET (возврат из прерывания); при его вызове происходит моментальный возврат. Hо прерывание 1CH интересно тем, что оно вызывается прерыванием таймера BIOS после того, как это прерывание обновило значение счетчика времени суток. Можно сказать, что это аппарат­ное прерывание, происходящее автоматически 18.2 раза в секунду. Вы можете изменить вектор этого прерывания так, чтобы он указывал на процедуру в Вашей программе. После этого Ваша процедура будет вызываться 18.2 раза в секунду. О том как написать и установить свою процедуру обработки прерывания см. в [1.2.3].

Hаписанная Вами процедура должна прочитать только что модифи­цированное значение счетчика времени суток, сравнить его с ожи­даемым временем, и выполнить то что требуется, когда ожидаемое время наконец наступит. Естественно, что когда время еще не по­дошло, то процедура просто возвращает управление, ничего не де­лая. Таким образом, процессор не выполняет лишней работы.

В приведенном примере процедура (не показанная здесь) запраши­вает у пользователя число минут (до 60), которое должно пройти до того, как раздастся звонок будильника. Это число, запасенное в MINUTES, умножается на 1092 для перевода в эквивалентное число импульсов счетчика времени суток. Для периода в пределах одного часа достаточно 16 бит - более длинные периоды требуют более сложных 32-битовых операций. Это число импульсов добавляется к младшему слову текущего значения счетчика времени суток и запоми­нается в ALARMCOUNT.

Затем вектор прерывания 1CH изменяется таким образом, чтобы он указывал на процедуру ALARM. Помните, что как только вектор будет изменен, ALARM будет автоматически вызываться 18.2 раза в секун­ду. При вызове эта процедура читает текущее значение счетчика времени суток через прерывание 1AH и сравнивает с ALARMCOUNT. При совпадении этих величин вызывается процедура BEEP (также не пока­занная здесь - см. [2.2.4]), которая выдает звуковой сигнал. В противном случае происходит возврат. Обычный код возврата из аппаратных прерываний (MOV AH,20H / OUT 20H,AL) включать в проце­дуру не нужно, так как он будет в прерывании таймера. Будьте внимательны и не забудьте сохранить изменяемые регистры.

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

MINUTES DW 0;хранит число минут до звонка

ALARMCOUNT DW 0;хранит счетчик времени для звонка

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

CALL REQUEST_MINUTES;запрос числа минут до звонка

MOV AX,MINUTES;пересылка в AX

MOV BX,1092;число импульсов счетчика в минуте

MUL BX;умножаем - результат в AX

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

MOV AH,0;номер функции чтения счетчика

INT 1AH;читаем значение, младший байт в DX

;складываем оба значения

ADD AX,DX;

MOV ALARMCOUNT,AX;получаем нужное значение счетчика

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

PUSH DS;сохраняем сегмент данных

MOV AX,SEG ALARM;берем сегмент процедуры ALARM

MOV DS,AX;помещаем его в DS

MOV DX,OFFSET ALARM;берем смещение процедуры

MOV AL,1CH;номер изменяемого вектора

MOV AH,25H;функция изменения вектора

INT 21H;меняем вектор

POP DS;восстанавливаем сегмент данных

;

;---дальше продолжается программа

;

;---в конце программы возвращаем вектор прерывания

MOV DX,0FF53H;оригинальные значения для

MOV AX,0F000H;прерывания 1CH

MOV DS,AX;помещаем сегмент в DS

MOV AL,1CH;номер изменяемого вектора

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

INT 21H;восстанавливаем вектор

;---процедура выдачи звукового сигнала

ALARM PROC FAR;создаем длинную процедуру

PUSH AX;сохраняем изменяемые регистры

PUSH CX;

PUSH DX;

;---читаем счетчик времени суток

MOV AH,0;номер функции чтения счетчика

INT 1AH;читаем значение счетчика

;---сравниваем с требуемым значением

MOV CX,ALARMCOUNT;берем требуемое значение

CMP DX,CX;сравниваем с текущим

JNE NOT_YET;если неравны, то на выход

;---выдаем звуковой сигнал, если значения совпали

CALL BEEP;эта процедура не показана

;---иначе возвращаемся из прерывания

NOT_YET: POP DX;восстанавливаем регистры

POP CX;

POP AX;

IRET;возврат из прерывания

ALARM ENDP;конец процедуры

 

2.1.8 Генерация случайных чисел с помощью микросхемы таймера.

Для генерации последовательности случайных чисел требуются сложные математические манипуляции. Hо иногда программе в опреде­ленный момент требуется только одно случайное число. В этом слу­чае случайное число может быть получено просто чтением из канала микросхемы таймера. Бейсик использует это число в качестве ядра, по которому генерируется случайная последовательность. Kонечно, Вы не можете использовать ряд последовательно считанных значений в качестве случайной последовательности, так как сами по себе интервалы времени между считываниями будут неслучайными.

100 RANDOMIZE TIMER 'сброс генератора случайных чисел

110 PRINT RND,RND,RND 'печать трех случайных чисел

в результате получаем:.7122483.4695052.9132487

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

Поскольку регистр счетчика канала таймера перезагружается снова и снова данным числом (а в промежутках идет счет вниз до

0), выберите в качестве загружаемого в счетчик значения число, равное требуемому диапазону случайных чисел. Hапример, для полу­чения случайного значения часа дня загружайте в счетчик 23.

Лучше всего использовать режим 3 канала 2 (порт 42H) микросхе­мы таймера [2.1.1]. Сначала установите для счетчика желаемый диапазон случайных чисел (в примере используется 10000, что при­водит к выдаче случайного числа в диапазоне от 0 <

Поделиться:





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



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