Насколько мне известно этот таймер - лучшее что есть под Windows Код: { Имя файла: HRTimer.PAS V1.00 Создан: Апр 17 1997, 06:40, автор John Mertus Обновлен #6: Окт 12 1997, 10:56 John Mertus Оболочка для таймера высокой точности при создании приложений под Win95/WinNT пример использования: Var HRT : THRTimer HRT := THRTimer.Create; HRT.StartTimer; Сброс таймера в ноль HRT.ReadTimer; Возвращает отсчитанное время в миллисекундах начиная со времени старта HRT.Free; } {-----------------Модуль HRTimer-------------------John Mertus Апрель 97---} Unit HRTimer; {-------------------Объявления-------------------------------} interface Uses Windows; Type THRTimer = Class(TObject) Constructor Create; destructor Destroy; override; Function StartTimer : Boolean; Function ReadTimer : Double; procedure Wait(mks: integer); private StartTime : int64; ClockRate : int64; public Exists : Boolean; End; {--------------------------Реализация-----------------------------------} implementation {------------------Create-------------------------John Mertus----Мар 97-} Constructor THRTimer.Create; { Получаем точное системное время и сохраняем его для дальнейшего использования.} BEGIN Inherited Create; QueryPerformanceFrequency(ClockRate); END; {------------------StartTimer---------------------John Mertus----Мар 97-} Function THRTimer.StartTimer : Boolean; { Получаем точное системное время и сохраняем его для дальнейшего использования.} BEGIN Result := QueryPerformanceCounter(StartTime); END; procedure THRTimer.Wait(mks: integer); var Counter, Freq, WaitUntil: Int64; begin if QueryPerformanceCounter(Counter) then begin QueryPerformanceFrequency(Freq); WaitUntil := Counter {+ WaitCal} + (mks * (Freq div 1000000)); while Counter < WaitUntil do QueryPerformanceCounter(Counter); end else Sleep(mks div 1000); end; {-------------------ReadTimer---------------------John Mertus----Мар 97---} destructor THRTimer.Destroy; begin inherited; end; Function THRTimer.ReadTimer : Double; Var ET : TLargeInteger; BEGIN QueryPerformanceCounter(ET); Result := 1000000.0*(ET - StartTime)/ClockRate; END; end.
Этот таймер применен для реализации системы управления шаговым приводом в программе GIGAMESH 1H Код: if not(TimeOut=0) then fHRT.Wait(TimeOut); //Задержка таймаута PortWork(Mask, 32); //Выдача в порт команды fHRT.Wait(PulseTime-TimeOut); //Задержка стола PortWork(fPortState, 32); //Возврат состояния порта
Из ЛС: Весьма интересные ссылки, спасибо!, особо - архивчик в конце второй ссылки (они правда на С++), у меня таймер реализован на QueryPerfomanceCounter - как в описании выше. Помог бы еслиб мог - я только по-наслышке знаю что такое OCX.
там они тоже используют QueryPerfomanceCounter но вызывают его ассемблером как я понял и используют что-то вроде калибровки. overhed что-ли... этот самый оверхэд позволяет им отсчитывать наносекунды. Также важно использование потоков. Сам я их не использовал но пытался разобраться (в VB) даже вроде как почти получилось. не довёл дело до конца. VB всё-таки не то что нужно по сравнению с дельфи или Си что касается написания таймеров.
Да, калибровку видел, правда пока не совсем понял сам принцип, да и сильно не разбирался в коде - пока нет необходимости. Впринципе таймер, который у меня реализован работает неплохо, есть конечно ньюансы кой какие: в GIGAMESH`е он работает в отдельном потоке, и, соответственно, этому потоку можно задать приоритет такой что винда вообще затыкается - тогда двигатели работают идеально, либо это должна быть машина с двухъядреным процессором - для такой машины тоже все отлично - винда выделяет для потока таймера одно ядро, а второе использует для собственных нужд и интерфейса.
Точное время: измеряем, применяем - статья на Хабре, насколько я понял QueryPerfomanceCounter не используется...