Hallo Forum,
ich hab folgendes Problem:
Ich hätte gerne Ereignisse im 10ms (oder kleiner) - Takt, die mir die CPU nicht verstopfen.
Habe hier schon etliches über genaue Zeitmessung, usw gelesen aber nicht das geeignete gefunden.
Was ich bisher getestet habe:
1.HighPrecision-Timer von TMS -> hält die 10ms recht gut ein, aber CPU-Last steigt auf 100%, da er die CPU-Ticks zählt.
2.TTimer mit Intervall 10ms liefert ca. alle 15-16ms einen Event auch wenn ich noch kleinere Zeiten einstelle.
3.Idee 2 TTimer mit 20ms um 10ms versetzt anstarten. Den Versatz habe ich über TMS HighprecisionDelay realisiert. -> 2 Ereignisse im 15ms-Raster + 1 Ereignis im 0ms-Raster.
Wie habe ich das herausgefunden:
Mit einem Button habe ich den Timer angestoßen, mit einem zweiten wieder gestoppt. Während der Timer lief habe ich mir die aktuellen Zeiten (now) und deren Differenzen in einen String schreiben lassen. Wenn gestoppt wurde habe ich den String in einer Memo ausgegeben. Auch den Now an sich habe ich überprüft indem ich am Anfang und am Ende der Routine die Zeit gemessen habe und die Differenz ausgeben habe.
Ich weiß, daß ein solches Verhalten machbar ist, denn ich habe es in NI LabView überprüft. -> 10ms Taktzeit Prozessorlast <5%
4.Nachdem ich das mit LabView hinbekommen habe, hab ich mir eine Delphi-
DLL gebaut die eine WM_USER-Message sendet. Diese
DLL habe ich in LabView verwendet um mir genaue Timing-Events zu senden. Die LabView-Routine habe ich wiederum als
DLL abgebunden und wieder in Delphi aufgerufen. Ergebnis war wie bei 2.
Anbei der Code für 2.) mit drei unterschiedlichen Varianten der Zeitermittelung zum Test.
Delphi-Quellcode:
unit TimerTest;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;
type
TForm1 =
class(TForm)
Timer1: TTimer;
Memo1: TMemo;
Button1: TButton;
Button2: TButton;
procedure Timer1Timer(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private-Deklarationen }
Msg :
string;
OldTime : TDateTime;
Freq : Int64;
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
FUNCTION TimeStamp:Int64;
asm
rdtsc
end;
FUNCTION TimeStampFrequency:int64;
var oldpriority:word; q0,q1,qf,ts0,ts1:int64; seconds:extended;
begin
oldpriority:=GetThreadPriority(GetCurrentThread);
SetThreadPriority(GetCurrentThread,THREAD_PRIORITY_TIME_CRITICAL);
QueryPerformanceCounter(q0);
ts0:=TimeStamp;
Sleep(200);
ts1:=TimeStamp;
QueryPerformanceCounter(q1);
SetThreadPriority(GetCurrentThread,oldpriority);
QueryPerformanceFrequency(qf);
seconds:=(q1-q0)/qf*1000;
result:=Trunc((ts1-ts0)/seconds+0.5);
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
CmdStart, CmdEnd : TDateTime;
i, j : Integer;
begin
// CmdStart := Now * 86400000;
// CmdStart := GetTickCount();
CmdStart := TimeStamp;
j := 1;
for i := 0
to 100
do
j := i;
// Msg := Msg + Format('%d %8.8fms ',[j,CmdStart-OldTime]);
Msg := Msg + Format('
%d %8.8fms ',[j,(CmdStart-OldTime)/Freq]);
// CmdEnd := Now * 86400000;
// CmdEnd := GetTickCount();
CmdEnd := TimeStamp;
// Msg := Msg + Format('%8.8fms',[CmdEnd-CmdStart])+#13#10;
Msg := Msg + Format('
%8.8fms',[(CmdEnd-CmdStart)/Freq])+#13#10;
OldTime := CmdStart
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Clear;
Msg := '
';
// OldTime := Now * 86400000;
// OldTime := GetTickCount();
OldTime := TimeStamp;
Timer1.Interval := 10;
Timer1.Enabled := True;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Timer1.Enabled := False;
Memo1.Text := Msg;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Freq := TimeStampFrequency;
end;
end.
Die Funktionen TimeStamp und TimeStampFrequency sind aus Eurem Beitrag "exakte Zeitmessungen auf Multiprozessoren" entnommen.
Hat irgendjemand eine Idee wie ich Delphi zu solchen Timing-Events überreden kann ohne die CPU zu blockieren?
Für Eure Hilfe Danke im voraus.