Ребят, помогите, не могу понять как работает таймер. В документации написано много и нудно, примеров не нашел. А мне надо сдеать задержку в программе на 100 мкс. Все перепробовал - не работает. Подскажите хоть что-нибудь, а? Чем отличается режим 0 от 1, режим 2 от 3? Неясно. Затем что есть такое GATE и чем отличается от OUT? Как получить текущее значение таймера? Может где есть русская документация по чипу 8254? Мне бы любая, очень хочу разобраться, несколько раз перечитывал доки от Интел'а, но не могу понять... Я ещё написал вот такой код, для пробы пера на паскале, как-то он работает, но непонятно ни почему он вообще работает, ни главное - как он работает... Код (Text): program f; var l,h:byte; prev:word; begin port[$40+3] := 54; port[$40] := $d0; port[$40] := 7; prev:= 1189; repeat l := port[$40]; h := port[$40]; if (prev - h*255+l) >= 1189 then begin prev := h * 255 + l; writeln(prev); port[$40+3] := 54; port[$40] := $d0; port[$40] := 7; end; until false; end. Ещё проблема в том, что программировать мне надо не системный (40н) таймер, а таймер на дополнительной плате. Но идея там та же самая, что и с системным. Что скажите?
1. есть книжка Джордейна (название забыл - типа, "Программирование IBM PC/AT" - у меня бумажная, но я слыхал об электронной - там есть раздел о таймере (я оттуда какую-то жужжалку на асме набирал). 2. на русском - поищи в старой литературе КР580ВИ53 - то же самое у меня есть книжка под рукой, но очень поверхностная: режим 0 - программируемая задержка режим 1 - ждущий мультивибратор режим 2 - делитель частоты режим 3 - генератор меандра режим 4 - строб с программным запуском режим 5 - строб с аппаратным запуском --- вот сюда глянь: http://www.computer-museum.ru/technlgy/i8253.php
Джорджейн есть на полочке , называется "Справочник программиста персональных компьютеров типа IBM PC/XT и AT" Там все очень подробно описано .
Diam Если напряг с документацией, ищи в Инете: А. и Г. Фроловы "Аппаратное обеспечение IBM PC", Глава 5. Там все разжевано до безобразия. В принципе, пойдет любой документ из Инета с ключевыми словами "таймер+канал+порт". Прога очень простая и не совсем правильная: 1189 - это начальное значение счетчика, которое каждые 0.84 мкс уменьшается на 2 (на PC в 3-м режиме), значит, до 0 досчитается через 500 мкс, а потом счетчик перезагрузится и вычитание пойдет снова. Этот момент и пытается поймать программа, и, кстати, может и пропустить. Лучше сделать что-то типа: Код (Text): port[$43] := 54; (* Заказать загрузку счетчика 0-го канала *) port[$40] := $d0; (* Мл. байт *) port[$40] := 7; (* Ст. байт *) prev:= 1189; (* Это типа значение из "предыдущего" цикла *) repeat port[$43]:=0; (* Защелкнуть счетчик - обязательно !!! особенно на медленных машинах *) port[$43]:=$D2; (* Запросить чтение мл/ст байтов счетчика - не обязательно, т.к. это default *) l := port[$40]; (* Мл. байт *) h := port[$40]; (* Ст. байт *) if (prev < h*255+l) then (* Время пошло вспять? *) begin writeln(prev); (* Кстати, вывод на экран очень медленный, лучше убрать *) (* Снова загрузить счетчик *) port[$43] := 54; port[$40] := $d0; port[$40] := 7; prev := 1189; end; prev := h * 255 + l; (* Обновить "предыдущее" значение *) until false; end. А вообще, мы для работы со временем в ДОСе юзали примерно такие процедуры на ламерском турбопасе: Код (Text): (***********************************************************) (* Количество тиков кварца системного таймера *) (* F=1193000 Гц, T=0.00000084с *) (***********************************************************) procedure GetQT( var t : extended ); var n : longint; (* Количество прерываний от таймера *) b0, b1 : byte; (* Младший и старший байты счетчика *) w : word; (* Значение счетчика *) o : byte; (* Значение сигнала OUT *) begin port[$43]:=$E2; (* Подготавливаем чтение упр. регистра *) o:=port[$40]; (* Читаем упр. регистр, 7-й бит - OUT *) n:=memL[$0:$46C]; (* Количество произошедших прерываний *) port[$43]:=0; (* Защелкиваем значение счетчика *) port[$43]:=$D2; (* Подготавливаем чтение счетчика *) b0:=port[$40]; (* Читаем младший байт счетчика *) b1:=port[$40]; (* Читаем старший байт счетчика *) w := word(b1)*256 + word(b0); t := (n-1)*65535.0 + ( (65535-w) div 2 ); if (o and $80)=0 then t := t + 32767.0; end; (* GetQT *) (**********************************************************) (* Количество тактов процессора *) (**********************************************************) procedure GetTT( var t : extended ); var a, b, c, d : word; begin asm sub ax, ax dw 0A20Fh (* CPUID *) dw 0310Fh (* RDTSC *) mov a, ax db 066h, 0C1h, 0E8h, 10h (* shr eax,16 *) mov b, ax mov c, dx db 066h, 0C1h, 0EAh, 10h mov d, dx end; t := a + b*65535.0 + c*655536.0*65536.0 + d*65536.0*65536.0*65536.0; end; (* GetTT *) (*********************************************************) (* Задержка в единицах, кратных 976 мкс. *) (* Для BIOS-ов, округляющих в большую сторону, d=0; *) (* для окугляющих в меньшую сторону d>=976 (i.e. 1000) *) (*********************************************************) procedure DelayB(n:word; d:word); var r : registers; i : word; begin r.ax := $8600; r.cx := 0; r.dx := d; for i:=1 to n do intr($15, r); end; (* DelayB *) Если таймер на доп. плате, то там будут другие порты и, не исключено, если GATE всегда=1, то декремент будет не 2, а 1.