Советы по Delphi


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


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



Содержание раздела