Форум: "WinAPI";
Текущий архив: 2005.01.02;
Скачать: [xml.tar.bz2];
ВнизПроблема с организацией работы с железкой через Com-порт... Найти похожие ветки
← →
Balkon (2004-11-18 16:11) [0]Приветствую, Мастера!
Будте добры, проконсультируйте.
Пишу программу для работы с некой железкой через com-порт.
Приложение организую следующим образом:
Имеется основной поток MainForm и вторичный поток AKRThread, в котором динамически создается объект ComPort (последний из ComPortLibv2.64 создает свой поток для работы с портом, но это не суть важно, я только ипользую его функции синхронной записи и чтения из порта, а также его событие ComPort.OnRxChar, возникающее по прилету информации в порт).
Организую выходную и входную очереди команд и ответов для устройства. В основном потоке выходная очередь заполняется, при каждом заполнении посылаю сообщение WM_COMANDWASADDED вторичному потоку, который достает команду из очереди и посылает в порт устройству. При получении ответов от устройства соответственно все наоборот со входной очередью.
Проблема в следующем:
Железка, обрабатывая команду (время до 2 сек, но в основном в течении нескольких миллисекунд), выдает ответ. Все данные которые прилетают во время обработки текущей команды теряются.
Т.о. во вторичном потоке нужно дожидаться ответа на каждую команду из очереди. Я это "как-то" реализовал: При записи команды в порт во вторичном потоке устанавливается флаг WaitForAnswer и снимается при получении ответа. Этот флаг проверяется при прилете сообщения от MainForm от том, что в выходную очередь поступила команда (WM_COMANDWASADDED). Если в этот момент происходит ожидание ответа, то отсылаю MainForm сообщение WM_TRYAGAIN, на что MainForm опять посылает сообщение WM_COMANDWASADDED потоку AKRThread. Т.о. из выходной очереди ничего не достается и не посылается в порт до тех пор, пока в потоке висит флаг ожидания ответа, а между основным и вторичным потоком циклом летают сообщения.
Все вроде работает, правда изредка за счет этого цикла сообщений использование процессора взлетает до 100% на пару секунд. Однако понимаю, что именно ожидание ответа от устройства вторичным потоком реализованио Коряво!(может даже фатально Коряво :))
Посоветуйте как можно правильнее организовать это ожидание.
Буду очень признателен за комментарии.
В любом случае спасибо что прочли. :)
← →
GanibalLector © (2004-11-19 02:00) [1]Могу помочь,но исключительно на API...без всяких там ComPortLibv2.64.А вообще-то статей навалом...особенно на королевстве.
← →
Германн © (2004-11-19 02:29) [2]2 Balkon (18.11.04 16:11)
Для начала объясни, что значит:
"я только ипользую его функции синхронной записи и чтения из порта, а также его событие ComPort.OnRxChar, возникающее по прилету информации в порт".
Синхронная запись и синхронное чтение - несовместимы с "Событием", также как событие OnRxChar - не совместимо с любой "синхронностью"!
← →
Balkon (2004-11-19 10:23) [3]>GanibalLector ©
>Могу помочь,но исключительно на API...без всяких там ComPortLibv2.64
Буду рад помощи. Но причем тут ComPortLibv2.64 :) Компонент исправно пишет и читает из порта (IMHO). Проблема в правильной идее построения приложения, которой как раз мне и не хватает.
>А вообще-то статей навалом...
Читал коечто. Про то как писать и читать из порта и т.п. Но проблема то не в этом.
← →
Balkon (2004-11-19 10:27) [4]>Германн ©
Вопрос терминологии.. Я не спец, возможно. Вот пример кода синхронной записи, чтение аналогично...
// perform synchronous write operation
function TCustomComPort.Write(const Buffer; Count: Integer): Integer;
var
AsyncPtr: PAsync;
begin
InitAsync(AsyncPtr);
try
WriteAsync(Buffer, Count, AsyncPtr);
Result := WaitForAsync(AsyncPtr);
finally
DoneAsync(AsyncPtr);
end;
end;
// perform asynchronous write operation
function TCustomComPort.WriteAsync(const Buffer; Count: Integer; var AsyncPtr: PAsync): Integer;
var
Success: Boolean;
BytesTrans: DWORD;
begin
if AsyncPtr = nil then
raise EComPort.CreateNoWinCode(CError_InvalidAsync);
PrepareAsync(okWrite, Buffer, Count, AsyncPtr);
Success := WriteFile(FHandle, Buffer, Count, BytesTrans, @AsyncPtr^.Overlapped)
or (GetLastError = ERROR_IO_PENDING);
if not Success then
raise EComPort.Create(CError_WriteFailed, GetLastError);
SendSignalToLink(leTx, True);
Result := BytesTrans;
end;
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2005.01.02;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.035 c