Модераторы: volvo877, Snowy, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Объясните про системный таймер $0040$006C; 
:(
    Опции темы
ausar
Дата 25.8.2008, 14:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 127
Регистрация: 3.8.2007

Репутация: нет
Всего: нет




Привет!
Помогите разобраться с системным таймером.Никак не могу заставить работать счетчик секунд
на основе системного таймера. Вот чего я достиг.
Итак доступ непосредственно к счетчику можно получить через

Код

var i:longint absolute $0040$006C;

begin
repeat;
write(i);
inc(t)
until t=1000;
End;



Везде написано что системный таймер производит 18.2 импульсов в сек. Скажем мне необходимо чтоб таймер отсчитывал секнды. Я понимаю что можно взять начальное показание таймера затем с каждым импульсом сравнивать его не достигло ли оно разницы в 18.2 и тогда увеличивать какой нибудь счетчик.
Но никак не могу это сделать. Все время тянет на что нибудь эдакое

Код

...
begin
z:=i {захватили начальное показание счетчика i}
repeat;{поставили цикл чтобы сравнивать текущее показание с ранее захваченным}
if i:=z+182 then inc (t); {на каждом витке сравниваем не достигла ли разница 182 т.е- 10 сек. Непонятно как заставить считать по 18.2)
until t=100
End.


Ну и вполне логично что как надо не получилось. 
PM MAIL   Вверх
Snowy
Дата 25.8.2008, 15:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: нет
Всего: 484



А не надо считать по 18.2
Это округлённая цифра.
Считай по 55.
Счётчик увеличивается на 1 каждые 55 милисекунд.
Соответственно пройденное время будет = (i-z) * 55 миллисекунд.
PM MAIL   Вверх
ausar
Дата 27.8.2008, 07:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 127
Регистрация: 3.8.2007

Репутация: нет
Всего: нет



Да нет мне нужно точно

Это сообщение отредактировал(а) ausar - 3.9.2008, 10:20
PM MAIL   Вверх
ausar
Дата 3.9.2008, 10:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 127
Регистрация: 3.8.2007

Репутация: нет
Всего: нет



Вот дошло дело и до завершения. Бьюсь вот над какой проблемой. Мне необходимо сделать часы которые при запуске перехватывают показания системных часов а потом при помощи таймера и прерываний отсчитывают время самостоятельно. В принципе проблема оказалась разрешимой. Количество импульсов - целое число т.е реально их в 1 сек полностью 18. Если так то часы будут отставать и спустя некоторое  время погрешность станет ощутимой. Но насколько я понял погрешность можно ликвидировать на каждой 5й секунде когда округленные .2 от 18.2  превратятся в 1 лишний импульс. Или яне прав? т.е если после каждой 5 сек прибавлять 1 импульс то часы должны идти отностительно ровно.

Я написал вот такое
Код

 {$M $1000,0,0}
Program q3;
Uses Crt,Dos;
Var OldVect:Procedure;
    i:longint absolute $0040:$006C;
    h,m,s,ms: word;
    cmp,ctime:longint;
    addimp:integer;


{Procedure PrintTime;
begin
write(#13,h,':',m,':',s,'[',ms,'] ');
End;}

{F+}
Procedure MyTimer; interrupt; {процедура перехвата прерывания}
begin
addimp:=0; {переменная добавляющая лишний импульс когда надо}
If i=cmp+91 then begin {если прошло 5 сек т.е 91 импульс то значит надо}
cmp:=i; 
addimp:=1; {сделали один лишний импульс}
End;
If i>ctime+18+addimp then begin {добавили лишний импульс если прошло 5 сек, или не добавили если не прошло}
ctime:=i;
inc(s);
End;
If s=60 then begin {ну а это сами часы тут все просто секунды минуты часы}
inc(m);
s:=0;
End;
If m=60 then begin
inc(h);
m:=0
End;
If h>23 then h:=0;
write(#13,h,':',m,':',s,'[',ms,'] ',addimp); {вывели на экран после каждого тика обновляем показания}
Inline ($9C);
OldVect;
End;
{F-}

begin
repeat
h:=0; m:=0; s:=0; ms:=0;
cmp:=i;
GetTime(h,m,s,ms);
until ms=0;
GetIntVec ($8, @OldVect);
SetIntVec ($8, Addr (myTimer));
Keep(0);



вроде бы теоретически все должно работать но. Почему же часы все равно через некоторое время начинают отставать?  Я сверяю с часами в нортоне т.е с ситемными часами из под дос. Может прога просто тормозит? Помогите разобраться в ситуации. 
PM MAIL   Вверх
Snowy
Дата 3.9.2008, 13:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: нет
Всего: 484



Цитата(ausar @  27.8.2008,  07:53 Найти цитируемый пост)
Да нет мне нужно точно
Так вот я тебе и говорю - если нужно точно, то забудь число 18.2
Точное число - 55
Каждый тик таймера = 55мс
А, если будешь использовать число 18.2, то со временем погрешность будет накапливаться, ибо, как видим, в одной секунде тиков не 18.2, а 1000мс / 55мс = 18.181818181818181818181818181818..... и т.д.
Если округлить, то получим пресловутые 18.2, но это число теоретическое. Использовать его нельзя, ибо погрешность.
PM MAIL   Вверх
ausar
Дата 3.9.2008, 15:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 127
Регистрация: 3.8.2007

Репутация: нет
Всего: нет



Так вот в этом то и смысл. Т.е действительно тиков реально 18 но в 1 сек их 18.2. Если мы будем отрезать эти 2 десятых доли тика то получим погрешность. Вот в я и бьюсь над тем чтобы погрешность ликвидировать. Если в сек 18.2 тиков то в минуте их 1092. Если мы будем считать каждую секунду только по 18 тиков то в нашей минуте у нас будет 1080 т.е на 12 меньше чем надо. Так вот идея и состоит чтобы вставить эти 12 тиков и добиться ровно счета не на секундах (все равно не заметно) а на минутах. На каждой 5 сек мы можем добавить 1 лишний тик чтобы в конце минуты у нас получилось ровно 1092 тика. 
Почему нельзя так? Почему нельзя просто постепенно компенсировать погрешность? Я вроде бы правильно все сделал в коде. Каждые 5 сек я добавляю лишний тик за счет того что в 6й секунде не 18 тиков а 19.
PM MAIL   Вверх
Snowy
Дата 3.9.2008, 15:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: нет
Всего: 484



Ты читаешь, что я пишу?

В СЕКУНДЕ НЕ 18.2 ТИКА!

И не 18 и не 19 и не 548 тиков.
Тик неделим. Длина одного тика 55 милисекунд.
Под секунду его не подогнать. И 0.2 тика перекидывать бессмысленно, ибо остаток меньше, чем 0.2
Цитата(ausar @  3.9.2008,  15:20 Найти цитируемый пост)
Если в сек 18.2 тиков то в минуте их 1092.
Вот именно. Если.
В секунде 1000/55 тиков, а не 18.2. Что равно 18.(18) тика.
Если ты считаешь, что в секунде 18.2 тика, то за минуту твои расчёты будут спешить более, чем на 1 секунду.
(18.2 - 18.(18) ) * 60 = 1.(09) секунды.
Кстати, в минуте не 1092 тика, а 1090.(90), или, если округлить, то 1090.91
Поэтому ещё раз говорю. Используй длину тика, а не количество тиков в секунде.
Я же написал, как измерить количество секунд.
(текущий тик - начальный тик) * 55 div 1000
Точное число - 55. А 18.2 - это приблизительное число, с помощью которого просто пытаются объяснить в учебнике.
Утверждать, что в секунде 18.2 тика, то же самое, что утверждать,что число Пи = 3.14
Да. Число Пи приблизительно равно 3.14. Но для расчётов такой точности мало.
Просто возьми калькулятор и раздели 1000 миллисекунд (то есть секунду) на длину одного тика (55 миллисекунд). 18.2 ты никак не получишь.
PM MAIL   Вверх
ausar
Дата 3.9.2008, 17:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 127
Регистрация: 3.8.2007

Репутация: нет
Всего: нет



Уж было закрыл тему но опять вот!

Это сообщение отредактировал(а) ausar - 4.9.2008, 04:08
PM MAIL   Вверх
ausar
Дата 4.9.2008, 04:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 127
Регистрация: 3.8.2007

Репутация: нет
Всего: нет



Я перестал считать по 18.2 и по 18 и по 19 и... А как посоветовал Snowy передал код и начал считать по 55. Получилось вот так

Код

 {$M $1000,0,0}
Program q3;
Uses Crt,Dos;
Var OldVect:Procedure;
    i:longint absolute $0040:$006C;
    h,m,s,ms: word;
    cmp,ctime:longint;
    addimp:integer;

Procedure PrintTime;
begin
write(#13,h,':',m,':',s,'[',ms,'] ');
End;

{F+}
Procedure MyTimer; interrupt; {процедура перехвата прерывания}
begin
If  (i-ctime)*55>1000 then begin {вот собственно и коррекция по сравнению с верхним кодом}
ctime:=i;
inc(s);
End;
If s=60 then begin {ну а это сами часы тут все просто секунды минуты часы}
inc(m);
s:=0;
End;
If m=60 then begin
inc(h);
m:=0
End;
If h>23 then h:=0;
write(#13,h,':',m,':',s,'[',ms,'] ',addimp); {вывели на экран после каждого тика обновляем показания}
Inline ($9C);
OldVect;
End;
{F-}
begin
repeat
h:=0; m:=0; s:=0; ms:=0;
cmp:=i;
GetTime(h,m,s,ms);
until ms=0;
GetIntVec ($8, @OldVect);
SetIntVec ($8, Addr (myTimer));
Keep(0);


Но это проблему не решило все равно показания моих часов постепенно начинают отличаться от системных. Что же это? Или это действительно порога так тормозит что показания начинают прыгать? Я заметил что при таком раскладе время время начинает отставать каждые 23 сек на 1 сек.

Это сообщение отредактировал(а) ausar - 4.9.2008, 07:12
PM MAIL   Вверх
volvo877
Дата 4.9.2008, 10:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2073
Регистрация: 15.11.2004

Репутация: 2
Всего: 116



ausar, Вот так не хочешь попробовать:
Код

{$M $1000,0,0}

Uses Crt,Dos;
Var
  OldVect: pointer;
  TimerVect: Procedure;

  hr, min, sec, hund: word;
  second_call: boolean;

Procedure PrintTime;
begin
  write(#13,hr,':',min,':',sec,'[',hund,'] ');
End;

{$F+}
Procedure MyTimer; interrupt;
begin
  if second_call then begin { <--- пропускаем каждый второй тик }

    inc(hund, 11); { 2 * 55 = 110 ms => 11 сотых, а не 5.5 }
    if hund >= 100 then begin
      dec(hund, 100); inc(sec); { <--- секунды сменились ... }

      if sec >= 60 then begin
        dec(sec, 60); inc(min);

        if min >= 60 then begin
          dec(min, 60); inc(hr);

          if hr >= 24 then dec(hr, 24);
        end;
      end;

      printtime; { ... секунды сменились, печатаем }
    end;

  end;
  Inline ($9C);
  TimerVect;

  second_call := not second_call;
end;
{$F-}

begin
  GetTime(hr,min,sec,hund);
  second_call := false; { <--- первый тик - пропускаем, второй - обрабатываем, и т.д. }

  GetIntVec ($8, @TimerVect);
  GetIntVec ($8, OldVect);
  SetIntVec ($8, Addr (myTimer));

  {
    С резидентом экспериментировать не буду, проверял обычным циклом
    Вроде все нормально...
  }

  repeat until keypressed;
  while keypressed do readkey;

  SetIntVec ($8, OldVect);
  {
    Keep(0);
  }
end.


Это сообщение отредактировал(а) volvo877 - 4.9.2008, 10:07
PM MAIL   Вверх
ausar
Дата 28.11.2008, 15:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 127
Регистрация: 3.8.2007

Репутация: нет
Всего: нет



И снова! Volvo877 твой код работает ровно. Но не пойму по какой причине примерно за 20 минут работы опять набирается погрешность примерно в 1 сек. Даже не знаю в чем причина. Пробовал запускать под голым досом, думал под виндой комп тормозит. 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi"
THandle
Rrader
volvo877

Запрещается!

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

2. Публиковать ссылки на варез

3. Оффтопить

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, THandle, Rrader, volvo877.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Object Pascal: кроссплатформенные технологии | Следующая тема »


 




[ Время генерации скрипта: 0.0554 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.