-
В отдельном треде раз в N-милисекунд посылаю в COM-порт определенную комманду. Комманда очень короткая - всего 3 символа. Посылку контролирую при помощи монитора COM-портов HHD Free Serial Port Monitor. Так вот - пока время между коммандами "большое" - комманды идут как и положено - одна за другой. Но при уменьшении промежутка времени меньше какой то величины - комманды "накопливаются", и поступают в COM-порт как бы пакетом (сразу порядка 20 "накопленных" комманд.) Вопрос: как этого избежать и контролировать чтоб комманты шли не пакетами? Время между коммандами должно быть максимально маленьким.
-
-
> Leonid Troyanovsky
Да я это помню! Но есть одно НО: к оборудованию, которым я управляю по ком-порту идет "пробная" программа. Так вот: если в этой программе я задаю допустим интервал 100Мс - там все идет как надо, не пакетами, а по одной комманде. А если делаю у себя в программе - пакетами. Выходит все же как то это можно контролировать?
-
Возможно это поможет: я пишу в ком-порт при помощи этой ф-ции
function TComPort.WriteBytes(ByteArray: Pointer; Count: integer): cardinal;
var
Signaled, RealWrite, BytesTrans: cardinal;
WriteOL: TOverLapped;
Success: boolean;
begin
Result := 0;
FillChar(WriteOL, SizeOf(WriteOL), 0);
WriteOL.hEvent := CreateEvent(nil, True, True, nil);
try
WriteFile(FHandle, ByteArray^, Count, RealWrite, @WriteOL);
Signaled := WaitForSingleObject(WriteOL.hEvent, INFINITE);
Success :=
(Signaled = WAIT_OBJECT_0) and
(GetOverlappedResult(FHandle, WriteOL, BytesTrans, False));
if not Success then
raise Exception.Create('Can not write to COM port!');
Result := RealWrite;
finally
CloseHandle(WriteOL.hEvent);
end;
end;
Ф-ция взята из очень хорошей книги "Работа с последовательным портом" - кажется так она называется.
-
> Alex_C (24.11.09 08:58) [3]
> я пишу в ком-порт при помощи этой ф-ции
Пардон, а зачем писать асинхронно? Если уж 3 байта.
-- Regards, LVT.
-
Что за мода такая - не анализировать рез-т вызова API-функциии ?
Ведь сказано же в справке :
If hFile was opened with FILE_FLAG_OVERLAPPED and lpOverlapped is not NULL, ..WriteFile may return before the write operation has been completed. In this case, WriteFile returns FALSE and the GetLastError function returns ERROR_IO_PENDING
may - это не must !
-
FlushFileBuffers для порта работает?
-
> Что за мода такая - не анализировать рез-т вызова API-функциии > ?
Поверил умной книжке - книга действительно классная и плюс единственная по работе с последовательными портами, где все так хорошо рассказано :) > ..WriteFile may return before the write operation has been > completed. In this case, WriteFile returns FALSE and the > GetLastError function returns ERROR_IO_PENDING
...WriteFile может возвратить результат до того, как операция будет завершена. В этом случае WriteFile возвратит False и функция GetLastError возвратит ERROR_IO_PENDING. Получается надо так:
function TComPort.WriteBytes(ByteArray: Pointer; Count: integer): cardinal;
var
Signaled, RealWrite, BytesTrans: cardinal;
WriteOL: TOverLapped;
Success: boolean;
y: Integer;
begin
Result := 0;
FillChar(WriteOL, SizeOf(WriteOL), 0);
WriteOL.hEvent := CreateEvent(nil, True, True, nil);
try
if not WriteFile(FHandle, ByteArray^, Count, RealWrite, @WriteOL) then
begin
y := GetLastError;
if y = ERROR_IO_PENDING then
WaitForSingleObject(WriteOL.hEvent, INFINITE);
end
else
Signaled := WaitForSingleObject(WriteOL.hEvent, INFINITE);
Success :=
(Signaled = WAIT_OBJECT_0) and
(GetOverlappedResult(FHandle, WriteOL, BytesTrans, False));
if not Success then
raise Exception.Create('Can not write to COM port!');
Result := RealWrite;
finally
CloseHandle(WriteOL.hEvent);
end;
end;
-
> FlushFileBuffers для порта работает?
Попробовал - не помогает!
-
> Получается надо так
Не получается.
Если WriteFile вернула True, то это означает, что запрошенная операция была успешно выполнена синхронно. Какой смысл ждать сигнал ивента и следом читать overlapped-результат, если операция заведомо успешно завершена на момент возврата из WriteFile ?
-
> Какой смысл ждать сигнал ивента и следом читать overlapped- > результат, если операция заведомо успешно завершена на момент > возврата из WriteFile ?
Ок! Понял! Так получается:
function TComPort.WriteBytes(ByteArray: Pointer; Count: integer): cardinal;
var
Signaled, RealWrite, BytesTrans: cardinal;
WriteOL: TOverLapped;
Success: boolean;
y: Integer;
begin
Result := 0;
FillChar(WriteOL, SizeOf(WriteOL), 0);
WriteOL.hEvent := CreateEvent(nil, True, True, nil);
try
if not WriteFile(FHandle, ByteArray^, Count, RealWrite, @WriteOL) then
begin
y := GetLastError;
if y = ERROR_IO_PENDING then
begin
Signaled := WaitForSingleObject(WriteOL.hEvent, INFINITE);
Success :=
(Signaled = WAIT_OBJECT_0) and
(GetOverlappedResult(FHandle, WriteOL, BytesTrans, False));
if not Success then
raise Exception.Create('Can not write to COM port!');
else
Result := BytesTrans;
end
else
raise Exception.Create('Can not write to COM port!');
end
else
Result := RealWrite;
finally
CloseHandle(WriteOL.hEvent);
end;
end;
-
Alex_C очень похоже, что Ваша беда называется FIFO последовательного порта!!! Ее можно рулить только в реестре(если программно) или ручками если зайти в система-девайсы-Ваш порт-пареметры порта-дополнительно(кнопка!) Установить надо ПОБАЙТНУЮ работу т.е. FIFO =1 в два ручья, тогда железяка не должна ждать уровня переполнения и сразу отдать системе. Второе. Надо в ините порта тоже поставить отдавать побайтно, т.е. чтобы уже связка(слой) система+драйвер не накапливали в буфере, а сразу трезвонили проге СОБЫТИЕ пришел(отправлен) байт! Если непонятно могу ширше... )
-
> Если непонятно могу ширше... )
Хотя бы общий пример хотелось бы!
-
Меня не было тут немного :) надеюсь интерес не погиб...! Ох-ох-ох.... тема то интересная, кто плавал уже, но разноплановая блин... с точки зрения комплексного затрагивания букета разных причин и свойств и пр...... ладно, придется подвинуть свою лень. Итак, сначала по поводу сказанного и "с чем его едят": HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ACPI\PNP0501\1\Device Parameters содержит 3 строковых параметра(текущие уставки) ответственных за FIFO COM1 порта в данном случае: ForceFifoEnable (вкл/выкл вообщем),RxFIFO,TxFIFO=размерчики. программно рулим естественно функциями работы с реестром. Стандартные функции, включая API винды фифо не рулят вообще! Лично я не находил даже упоминания об этом...
-
Работу фифо прочувствовать просто. Берем терминалочку, например мне нравится в таких случаях эта http://kolibdb.100free.com/files/wTerm.zipдалее соединяем два порта COM1+COM2 простейшим нульмодемным соединением Tx1+Rx2 и Rx1+Tx2. Затем запуск двух копий приложения и открытие этих портов с минимальной скоростью. Давим и удерживаем символьную клавишу и лицезреем, как на приемной стороне БАЙТЫ ПОЛУЧАЮТСЯ и отображаются ПАЧКАМИ= FIFO обьема! Т.е. они выплевываются, скажем по 8 байт, видно, что накапливаются и именно выплевываются, достигнув порога срабатывания. Рулим FIFO и зрим эффект. Помимо фифо в сабже "замешаны" параметры при открытии порта, а именно "...Поля структуры COMMTIMEOUTS...".
-
В связи с этим НАСТОЯТЕЛЬНО советую перечитать статейку "Работа с коммуникационными портами (COM и LPT) в программах для Win32" (например тут http://www.citforum.ru/hardware/articles/comports/) ЭТО КАЧЕСТВЕННЫЙ ПРОФЕССИОНАЛЬНЫЙ ПОДХОД при оседлании последовательных портов в WIN32! Для многих сведения там излагаемые просто открытие глаз на принципы и то как надо грамотно писать коммуникационные проги, особенно, когда работа идет с N портами одновременно (мультипортовка). Еще важно знать это: "Точное время: измеряем, применяем" ( http://habrahabr.ru/blogs/delphi/75234/) Вот ИМЕННО на ПЕРЕСЕЧЕНИИ этих 3-х китов и только после хотябы вникания(лучше изучения) будет истина(решение) проблем сабжа и иже с ним. Подобные вещи ипроблемы неоднократно возникают у спецов работающих с железом, контроллерами, сетями "нижнего уровня" и их протоколами, напрмер MODBUS и проблемы полудуплекса RS-485.... Считаю, что выдал обильную инфу, переборов свою лень и ничего не закуркулил :) успехов и продвинутых результатов!
-
> надеюсь интерес не погиб...!
Интерес очень большой :) Темя для меня очень важная - хочу досканально в ней разобраться. Спасибо за инфо - буду читать и разбираться!
|