Помогите с таймером 8254!!!

Тема в разделе "WASM.ELECTRONICS", создана пользователем Diam, 3 апр 2006.

  1. Diam

    Diam New Member

    Публикаций:
    0
    Регистрация:
    3 апр 2006
    Сообщения:
    4
    Ребят, помогите, не могу понять как работает таймер. В документации написано много и нудно, примеров не нашел. А мне надо сдеать задержку в программе на 100 мкс. Все перепробовал - не работает. Подскажите хоть что-нибудь, а? Чем отличается режим 0 от 1, режим 2 от 3? Неясно. Затем что есть такое GATE и чем отличается от OUT? Как получить текущее значение таймера?

    Может где есть русская документация по чипу 8254? Мне бы любая, очень хочу разобраться, несколько раз перечитывал доки от Интел'а, но не могу понять...

    Я ещё написал вот такой код, для пробы пера на паскале, как-то он работает, но непонятно ни почему он вообще работает, ни главное - как он работает...
    Код (Text):
    1.  
    2. program f;
    3. var
    4. l,h:byte;
    5. prev:word;
    6. begin
    7.  
    8. port[$40+3] := 54;
    9. port[$40] := $d0;
    10. port[$40] := 7;
    11. prev:= 1189;
    12. repeat
    13.     l := port[$40];
    14.     h := port[$40];
    15.     if (prev - h*255+l) >= 1189 then
    16.     begin
    17.          prev := h * 255 + l;
    18.          writeln(prev);
    19.          port[$40+3] := 54;
    20.          port[$40] := $d0;
    21.          port[$40] := 7;
    22.     end;
    23. until false;
    24. end.
    25.  


    Ещё проблема в том, что программировать мне надо не системный (40н) таймер, а таймер на дополнительной плате. Но идея там та же самая, что и с системным.

    Что скажите?
     
  2. shoo

    shoo New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2003
    Сообщения:
    1.537
    Адрес:
    Ukraine
    1. есть книжка Джордейна (название забыл - типа, "Программирование IBM PC/AT" :)- у меня бумажная, но я слыхал об электронной - там есть раздел о таймере (я оттуда какую-то жужжалку на асме набирал).

    2. на русском - поищи в старой литературе КР580ВИ53 - то же самое

    у меня есть книжка под рукой, но очень поверхностная:

    режим 0 - программируемая задержка

    режим 1 - ждущий мультивибратор

    режим 2 - делитель частоты

    режим 3 - генератор меандра

    режим 4 - строб с программным запуском

    режим 5 - строб с аппаратным запуском

    ---

    вот сюда глянь:

    http://www.computer-museum.ru/technlgy/i8253.php
     
  3. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
    Джорджейн есть на полочке , называется "Справочник программиста персональных компьютеров типа IBM PC/XT и AT"

    Там все очень подробно описано .
     
  4. drmad

    drmad New Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    332
    Адрес:
    Russia
    Diam



    Если напряг с документацией, ищи в Инете: А. и Г. Фроловы "Аппаратное обеспечение IBM PC", Глава 5. Там все разжевано до безобразия. В принципе, пойдет любой документ из Инета с ключевыми словами "таймер+канал+порт".



    Прога очень простая и не совсем правильная: 1189 - это начальное значение счетчика, которое каждые 0.84 мкс уменьшается на 2 (на PC в 3-м режиме), значит, до 0 досчитается через 500 мкс, а потом счетчик перезагрузится и вычитание пойдет снова. Этот момент и пытается поймать программа, и, кстати, может и пропустить. Лучше сделать что-то типа:


    Код (Text):
    1.  
    2. port[$43] := 54; (* Заказать загрузку счетчика 0-го канала *)
    3. port[$40] := $d0; (* Мл. байт *)
    4. port[$40] := 7; (* Ст. байт *)
    5. prev:= 1189; (* Это типа значение из "предыдущего" цикла *)
    6. repeat
    7.     port[$43]:=0;   (* Защелкнуть счетчик - обязательно !!! особенно на медленных машинах *)
    8.     port[$43]:=$D2; (* Запросить чтение мл/ст байтов счетчика - не обязательно, т.к. это default *)
    9.     l := port[$40]; (* Мл. байт *)
    10.     h := port[$40]; (* Ст. байт *)
    11.     if (prev < h*255+l) then (* Время пошло вспять? *)
    12.     begin
    13.          writeln(prev); (* Кстати, вывод на экран очень медленный, лучше убрать *)
    14.          (* Снова загрузить счетчик *)
    15.          port[$43] := 54;
    16.          port[$40] := $d0;
    17.          port[$40] := 7;
    18.          prev := 1189;
    19.     end;
    20.     prev := h * 255 + l; (* Обновить "предыдущее" значение *)
    21. until false;
    22. end.
    23.  




    А вообще, мы для работы со временем в ДОСе юзали примерно такие процедуры на ламерском турбопасе:


    Код (Text):
    1.  
    2. (***********************************************************)
    3. (* Количество тиков кварца системного таймера              *)
    4. (* F=1193000 Гц, T=0.00000084с                             *)
    5. (***********************************************************)
    6. procedure GetQT( var t : extended );
    7.  var
    8.   n      : longint; (* Количество прерываний от таймера *)
    9.   b0, b1 : byte;    (* Младший и старший байты счетчика *)
    10.   w      : word;    (* Значение счетчика *)
    11.   o      : byte;    (* Значение сигнала OUT *)
    12. begin
    13.   port[$43]:=$E2;   (* Подготавливаем чтение упр. регистра *)
    14.   o:=port[$40];     (* Читаем упр. регистр, 7-й бит - OUT  *)
    15.   n:=memL[$0:$46C]; (* Количество произошедших прерываний *)
    16.   port[$43]:=0;     (* Защелкиваем значение счетчика *)
    17.   port[$43]:=$D2;   (* Подготавливаем чтение счетчика *)
    18.   b0:=port[$40];    (* Читаем младший байт счетчика *)
    19.   b1:=port[$40];    (* Читаем старший байт счетчика *)
    20.   w := word(b1)*256 + word(b0);
    21.   t := (n-1)*65535.0 + ( (65535-w) div 2 );
    22.   if (o and $80)=0 then t := t + 32767.0;
    23. end; (* GetQT *)
    24.  
    25. (**********************************************************)
    26. (* Количество тактов процессора                           *)
    27. (**********************************************************)
    28. procedure GetTT( var t : extended );
    29.  var a, b, c, d : word;
    30. begin
    31.  asm
    32.    sub ax, ax
    33.    dw 0A20Fh                (* CPUID *)
    34.    dw 0310Fh                (* RDTSC *)
    35.    mov a, ax
    36.    db 066h, 0C1h, 0E8h, 10h (* shr eax,16 *)
    37.    mov b, ax
    38.    mov c, dx
    39.    db 066h, 0C1h, 0EAh, 10h
    40.    mov d, dx
    41.  end;
    42.  t := a + b*65535.0 + c*655536.0*65536.0 + d*65536.0*65536.0*65536.0;
    43. end; (* GetTT *)
    44.  
    45. (*********************************************************)
    46. (*  Задержка в единицах, кратных 976 мкс.                *)
    47. (*  Для BIOS-ов, округляющих в большую сторону, d=0;     *)
    48. (*  для окугляющих в меньшую сторону d>=976 (i.e. 1000)  *)
    49. (*********************************************************)
    50. procedure DelayB(n:word; d:word);
    51.  var r : registers; i : word;
    52. begin
    53.   r.ax := $8600;
    54.   r.cx := 0;
    55.   r.dx := d;
    56.   for i:=1 to n do intr($15, r);
    57. end; (* DelayB *)
    58.  




    Если таймер на доп. плате, то там будут другие порты и, не исключено, если GATE всегда=1, то декремент будет не 2, а 1.