Форум: "Система";
Текущий архив: 2002.12.30;
Скачать: [xml.tar.bz2];
Вниз
Как сделать таймер с задержкой меньше 1 мс? Найти похожие ветки
← →
lmd_sting (2002-10-23 14:09) [0]Возник такой трабл. Нужно реализовать принятие данных из com порта . Если считывать информацию из буфера то без проблем достигается скорость около 11 кб/c . Но контроллер передает по одному байту потом ждет ответа от компа. Стандартный таймер имеет минимальную задержку в 1 мс , т.е. я проверяю буфер достаточно редко и скорость резко падает. Может кто нибудь знает как это реализуется или я думаю не в том направлении?
← →
Opuhshii (2002-10-23 14:14) [1]у Стандартного таймера минимальная задержка больше 1 мс .. смотри FAQ
← →
Bis (2002-10-23 15:18) [2]а зачем это делать по таймеру?
← →
Anatoly Podgoretsky (2002-10-23 15:25) [3]Без таймера спокояно передается до 90 кб в секунду, просто быстрее компорт не попадался
← →
lmd_sting (2002-10-24 12:30) [4]А как это реализовать без таймера? Каким образом можно передавать со скоростью 90 кб/c если IMHO com расчитан максимум на 128000 кбит/c (16 кб/c) хотя реально я устанавливал скорость только на 115200 если больше то выдавалась ошибка инициализации порта.
← →
lmd_sting (2002-10-24 12:35) [5]Есть какие нибудь события по которым можно определить пришли ли данные в ком порт?
← →
sunsb (2002-10-25 02:35) [6]Сам я им не пользовался, но в демках DX для Делфи
он используется сплош и рядом. Надеюсь немца вы найдете ))).
unit DXTimer; // 22-OCT-98 as (Arne Schдpers)
Overhead: P-166 Win95
1 Timer, 20 msec (50 Events) 4%
5 Timer, 20 msec (250 Events) 13%
25 Timer, 100 msec (250 Events) 16%
25 Timer, 20 msec (1000 Events) 37%
1 Timer, 1 msec (1000 Events) 35%
Grenze fьr Win95: 3000 Events/sec sync, 15000 Events async
Bei 1000 Events/sec benцtigt Synchronize rund 15%
MODs 06-MAR-99: Typecasts von MaxWait, NextTick wg. Delphi 4.
Vernьnftig unter einen Hut bringen lдЯt sich das nicht, weil
D3 auch bei Cardinal gnadenlos ein Vorzeichen reinhaut...
}
interface
uses Windows, SysUtils, Classes, MMSystem;
type
TDXTimer = class(TComponent)
private
FInterval: Cardinal; // echte Millisekunden
FOnTimer, FOnAsyncTimer: TNotifyEvent;
FEnabled: Boolean;
StartTickTime, NextTick: Integer; // Zeitrahmen
TimerThread: TThread; // TDXTimerThread (implementation)
procedure UpdateTimer; // XRef: Set..., Destroy
procedure SetEnabled(Value: Boolean);
procedure SetInterval(Value: Cardinal);
procedure SetOnTimer(Value: TNotifyEvent);
procedure SetOnAsyncTimer(Value: TNotifyEvent);
protected
procedure Timer; // per Synchronize
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property Enabled: Boolean read FEnabled
write SetEnabled default True;
property Interval: Cardinal read FInterval
write SetInterval default 20;
property OnTimer: TNotifyEvent // synchron
read FOnTimer write SetOnTimer;
property OnAsyncTimer: TNotifyEvent // asynchron
read FOnAsyncTimer write SetOnAsyncTimer;
end;
implementation
type // intern verwendeter Thread
TDXTimerThread = class(TThread)
private
Owner: TDXTimer;
TimerEvent: THandle; // zum Warten und fьr Updates
public
constructor Create(AOwner: TDXTimer);
destructor Destroy; override;
procedure Execute; override;
procedure Terminate;
end;
constructor TDXTimer.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FEnabled := True; FInterval := 20;
TimerThread := TDXTimerThread.Create(Self);
end;
destructor TDXTimer.Destroy;
begin
FEnabled := False; UpdateTimer; // Timer aus
TimerThread.Terminate;
inherited Destroy;
end;
procedure TDXTimer.UpdateTimer;
begin
StartTickTime := timeGetTime;
NextTick := StartTickTime+Integer(Interval);
SetEvent(TDXTimerThread(TimerThread).TimerEvent);
end;
procedure TDXTimer.SetEnabled(Value: Boolean);
begin
if Value = FEnabled then Exit;
FEnabled := Value; UpdateTimer;
end;
procedure TDXTimer.SetInterval(Value: Cardinal);
begin
if Value = FInterval then Exit;
FInterval := Value; UpdateTimer;
end;
procedure TDXTimer.SetOnTimer(Value: TNotifyEvent);
begin
FOnTimer := Value; UpdateTimer;
end;
procedure TDXTimer.SetOnAsyncTimer(Value: TNotifyEvent);
begin
FOnAsyncTimer := Value; UpdateTimer;
end;
procedure TDXTimer.Timer;
begin
if Assigned(FOnTimer) then FOnTimer(Self);
end;
// ------------- TDXTimerThread -----------------
constructor TDXTimerThread.Create(AOwner: TDXTimer);
begin
inherited Create(False);
Owner := AOwner;
TimerEvent := CreateEvent(nil, False, False, nil);
FreeOnTerminate := True;
end;
procedure TDXTimerThread.Terminate;
begin
inherited Terminate;
SetEvent(TimerEvent); // sonst wartet der ewig...
end;
destructor TDXTimerThread.Destroy;
begin
CloseHandle(TimerEvent);
inherited Destroy;
end;
procedure TDXTimerThread.Execute;
var MaxWait, WaitResult: Integer;
begin
while not Terminated do
begin
with Owner do
if Enabled and (Assigned(FOnTimer) or
Assigned(FOnAsyncTimer)) then
begin
MaxWait := Cardinal(NextTick)-timeGetTime;
if MaxWait <= 0 then
begin // Breakpoints bei der Entwicklung erzeugen sonst
if -MaxWait > 10*Integer(Interval) // *sehr* eilige Timer..
then NextTick := timeGetTime;
MaxWait := 0;
end;
end
else MaxWait := Integer(INFINITE);
if MaxWait = 0 then WaitResult := WAIT_TIMEOUT
else WaitResult := WaitForSingleObject(TimerEvent,MaxWait);
case WaitResult of
WAIT_OBJECT_0: ; // neue Werte
WAIT_TIMEOUT:
with Owner do
begin
Inc(NextTick,Interval);
// zuerst ein eventueller asynchroner, dann ein
// synchronisierter Aufruf
if Assigned(FOnASyncTimer) then OnASyncTimer(Owner);
if Assigned(FOnTimer) then Synchronize(Timer)
end;
else
raise Exception.Create
(Format("DXTimer: WaitResult = %d?",[WaitResult]));
end;
end;
end;
end.
www : http://sunsb.dax.ru , http://sunsb.narod.ru
← →
Aleks1 (2002-10-25 04:24) [7]Я и сам, нередко, использую в подобных задачах таймер. Но лишь для того только, чтобы не насиловать железо. Пусть у него будет время жить своей жизнью.
Но, во-первых, драйвер порта всегда сообщает о том, что что-то принято! Во-вторых тот же драйвер сообщает, что что-послано! Следовательно, весьма логично писать подобную задачу используя эти события!
← →
lmd_sting (2002-10-25 10:44) [8]Каким образом он это сообщает (какое при этом возникает событие)? Я щас это узнаю путем проверки количиства байт в буфере.
← →
Странник (2002-10-25 11:06) [9]а ты лови соответствующее событие...
procedure TComThread.Execute;
var
EventHandles: Array[0..1] of THandle;
Overlapped: TOverlapped;
Signaled, BytesTrans: DWORD;
begin
FillChar(Overlapped, SizeOf(Overlapped), 0);
Overlapped.hEvent := CreateEvent(nil, True, True, nil);
EventHandles[0] := FStopEvent;
EventHandles[1] := Overlapped.hEvent;
repeat
WaitCommEvent(FComPort.Handle, FMask, @Overlapped);
Signaled := WaitForMultipleObjects(2, @EventHandles, False, INFINITE);
case Signaled of
WAIT_OBJECT_0: Break;
WAIT_OBJECT_0 + 1:
if GetOverlappedResult(FComPort.Handle, Overlapped, BytesTrans, False)
then DispatchComMsg;
else Break;
end;
until False;
PurgeComm(FComPort.Handle, PURGE_TXABORT or PURGE_RXABORT or
PURGE_TXCLEAR or PURGE_RXCLEAR);
CloseHandle(Overlapped.hEvent);
CloseHandle(FStopEvent);
end;
← →
Шуррик (2002-10-25 11:25) [10]Доп. вопрос: мне тоже нужен таймер, но не для кома, хотя он будет использоваться впоследствии и именно частоту его событий (и еще чуть быстрее) я собираюсь (пока) эмулировать. Один из вариантов - запустить на модеме Локал Аналог Лупбак - и использовать его события. Вообще, никто такой фихой раньше не занимался?
← →
Steven Deathman (2002-10-26 09:49) [11]Проще взять стандартный объект, например Async32? Он сам все за тебя сделает. У меня работает обмен с микроконтроллером на 57600 без проблем, а между компами на 115200.
Страницы: 1 вся ветка
Форум: "Система";
Текущий архив: 2002.12.30;
Скачать: [xml.tar.bz2];
Память: 0.81 MB
Время: 2.043 c