Организация задержки - все еще большая головная в Delphi. Я использую Delphi 1 и пытаюсь организовать задержку 2 ms с погрешностью -0 ms +1 ms. Может кто-то уже решал подобную проблему? Организация цикла не позволяет достичь такой точности. Стандартный таймерный компонент не позволяет работать с частотой выше чем 18.2 times/sec.
Приведу модуль, который я использовал при создании 16-битного хранителя экрана (screen saver). В нем есть переменная DelayInit, объявленная глобально и инициализируемая во время создания формы как показано ниже:
DelayInit := False; Delay(0); {Проводим инициализацию и присваиваем 0 для дальнейшей калибровки} |
Этим мы указываем на необходимость калибровки для конкретной системы.
unit Globals; interface Uses WinProcs, WinTypes, Messages,Classes, Graphics, IniFiles; Const OT_USER = 1; Var SsType : Integer; { iObjL : Integer; { Текущая левая координата объекта } { iObjR : Integer; { Текущая правая координата объекта } { iObjT : Integer; { Текущая верхняя координата объекта } Finish : Boolean; TestMode : Boolean; { True если режим тестирования } LoopsMs : LongInt; { Ms циклов } ScreenWd : Integer; { Ширина экрана } ScreenHt : Integer; { Высота экрана } SpotSize : Integer; { Размер точки } SpotSpeed : Integer; { Скорость точки } DelayInit : Boolean; { True если цикл задержки инициализирован } Procedure Delay(Ms : Integer); { Задержка для Ms миллисекунд } Procedure CursorOff; { Включение курсора } Procedure CursorOn; { Выключение курсора } {$IFDEF NOVELL} {$ENDIF} implementation Uses SysUtils, Toolhelp; Procedure CursorOff; { Выключение курсора } Var Cstate : Integer; { Текущее состояние курсора } Begin Cstate := ShowCursor(True); { Получаем состояние } While Cstate >= 0 do Cstate := ShowCursor(False); { Пока состояние >= 0 курсор выключен } End; Procedure CursorOn; { Выключаем курсор } Var Cstate : Integer; { Текущее состояние курсора } Begin Cstate := ShowCursor(True); { Получаем состояние } While Cstate < 0 do Cstate := ShowCursor(True); { Пока состояние < 0 курсор включен } End; Procedure Delay(Ms : Integer); { Задержка для Ms миллисекунд } {Если Ms равно 0, проводим калибровку } Var L,MaxLoops,StartL,EndL,Down,Up,Res : LongInt; { Локальные переменные } Ti : TTimerInfo; Begin Up := 0; Down := 100000; if Not DelayInit then begin Ti.dwSize := sizeof(LongInt) * 3; TimerCount(@Ti); StartL := Ti.dwmsSinceStart; { Получаем время старта } if Not DelayInit then begin { Включаем тест } for L := 0 to 100000 do begin { Организуем цикл с числом проходов равным 100000 } Dec(Down); { Уменьшаем счетчик } Res := Abs(Down - Up); { Разница } if Res = 0 then Inc(Res); { Сверка } Inc(Up); { Приращение } end; end; TimerCount(@Ti); EndL := Ti.dwmsSinceStart; { Получаем время старта } LoopsMs := 100000 Div (EndL - StartL); { Вычисляем показатель MS } DelayInit := True; { Откалибровали } end else begin if Ms = 0 then Exit; MaxLoops := LoopsMs * Ms; { Получаем необходимое количество циклов } for L := 0 to MaxLoops do Begin { Организация цикла } Dec(Down); { Уменьшаем счетчик } Res := Abs(Down - Up); { Получаем разницу } if Res = 0 then Inc(Res); { Сверка } Inc(Up); { Приращение } end end; End; end. |