Организация задержки

Организация задержки - все еще большая головная в 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.

 
« Предыдущая статья   Следующая статья »