![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
COM порт, асинхронные чтение запись
REA © (2008-05-16 10:41:00)Помогите с вопросом. Уже мозг сломал.
Сделал чтение COM порта и периодически теряются байтики. В результате получился такой код:
FillChar(IO, SizeOf(IO), 0);
IO.hEvent := FIOEvent; // Overlapped
ToRead := 2; // Допустим 2
RdRes := ReadFile(idComm, Buf[1], ToRead, Bytes, @IO);
If (Not RdRes) And (GetLastError = ERROR_IO_PENDING) Then
RdRes := WaitForSingleObject(FIOEvent, 500) = 0; // Limit frame reading by 500 msec
If (RdRes) Then
RdRes := GetOverlappedResult(idComm, IO, Bytes, False);
If RdRes And (Bytes = ToRead) Then
и вот тут при RdRes = True число байт (Bytes) = 0.
Что я неправильно делаю?
JUDAS (2009-01-11 16:52:00) [1]Удалено модератором
Примечание: Задай вопрос в своей ветке
REA (2008-05-27 15:21:00) [2]>Вынеси всю эту беду в отдельный поток пусть се спит скока влезет.
так и есть
>Можь ваще там синхронно читать, поставить таймаут милисек 500
Так и было - см. выше. А похоже оно и в синхронном режиме кадры теряет, т.е. может проблема еще и в самой железке.
>Давай, кажи таймауты и описалово протокола.
Он длинный. Подобие SDLC
ага0 (2008-05-27 12:05:00) [3]
> Без них не работает в таком виде как сейчас
Естессно, нать как я писал.
> то иногда будет подвисать в WaitFSO.
Вот те и ответ - есть дыры между посылками. Неча читать она и висит. А ставишь таймаут - она по нему выкидыват. Тут ты ноль и читашь. Тут прынцип какой - не дергаться без нужды. Пришли байтики - читаем, нет - сопим в тряпочку то бишь спим. Вынеси всю эту беду в отдельный поток пусть се спит скока влезет. Можь ваще там синхронно читать, поставить таймаут милисек 500 - Terminate проверять и все дела. Хотя по мне асинхронка удобней даж в отдельном потоке, управляемость выше.
> Межбайтовый таймаут особенно не влияет на результат
Ты чет иль путаешь иль оценивашь результат. Должны влиять. Если канечна я чего по склерозности не путал:) Давай, кажи таймауты и описалово протокола. Будет время помедитирую.
REA (2008-05-27 10:05:00) [4]>Ежель неуверенно чуйствуешь себе в таймаутах порта, то есть железный способ - отключить их нафиг.
Без них не работает в таком виде как сейчас. Неуверенно чувствую, потому что результаты получаются непредсказуемые. В принципе можно и так сделать, как ты описал, но проще сделать самому тогда уж буферизацию и читать одним куском с выходом из чтения по таймауту. Но медленнее будет. Хотя в этом случае придется и логику программы переделывать...
Пакеты идут сильно периодично - практически всегда, когда не передаются данные.
>Вызываешь ClearComError - смотришь сколько пришло. Таймауты порта на старом железе и при хорошей длине кабеля - вещь важная.
Железо нормальное хоть и самодельное. Кабель тоже не длинный - метра 3-4. Попробую ClearComError еще, но сдается мне монитор правильно показывает.
tesseract (2008-05-26 21:44:00) [5]
> Ежель там EV_RXCHAR, вызываешь ReadFile
Вызываешь ClearComError - смотришь сколько пришло. Таймауты порта на старом железе и при хорошей длине кабеля - вещь важная.
ага0 (2008-05-26 18:25:00) [6]
> то все работало. кажется...
Креститься надо, када кажется:) Шютка, не обижайся. Ежель неуверенно чуйствуешь себе в таймаутах порта, то есть железный способ - отключить их нафиг. Далее ставишь маску эвентов SetCommEvent ждешь прихода байтов асинхронным вызовом WaitCommEvent с ...WaitFor... и нужным по логике приложения таймаутом или бесконечно. На срабатывание делаешь GetOverlappedResult и смотришь маску, которую передавал в WaitCommEvent. Ежель там EV_RXCHAR, вызываешь ReadFile и читаешь либо все, что пришло, либо сколько нужно до полного пакета. Далее цикл по новой - WaitCommEvent etc. Набрав целый пакет, вызываешь его обработку. Способ железобетонный, когда девайс шлет не шибко периодично, то пусто то густо. Если пакеты идут с хорошей периодичностью, то да, таймауты порта удобны, а иначе - ну их нахвиг.
REA (2008-05-26 17:53:00) [7]>Лучше событие пересоздавать. А то при многопоточности, ерунда может выйти.
Пробовал, то же самое.
>Ну и иде настройка порта? Я почему спрашиваю-та - ежель
Уж какие я только не ставил вариации из таймаутов. Межбайтовый таймаут особенно не влияет на результат, а вот общий таймаут на чтение, если не поставить, то иногда будет подвисать в WaitFSO.
Сейчас стоит межбайтовый 1мс и общий 50 мс.
Действительно, в мониторе на операции чтения написано сейчас TIMEOUT, но откуда бы ему взяться? Если читать одним куском, а не как сейчас в два захода, то все работало. кажется...
ага0 (2008-05-26 15:54:00) [8]Ну и иде настройка порта? Я почему спрашиваю-та - ежель
> ошибок при чтении и ожидании не возникает, но кадры куда
> то теряются - GetOverlappedResult возвращает 0 байт (если
> снова попытаться прочитать ReadFile, то все равно 0 байт
> и таймаутов никаких не возникает). Т.е. как бы данные есть,
> но их 0.
то возможно чтение завершается по таймауту порта, тыж статус порта не проверяешь
tesseract (2008-05-26 15:30:00) [9]
> IO.hEvent := FIOEvent;
Лучше событие пересоздавать. А то при многопоточности, ерунда может выйти.
REA (2008-05-26 14:44:00) [10]Сейчас локальная функция чтения выглядит так:
Function ReadAsync: Boolean;
Var
IO: TOverlapped;
WaitRes: Integer;
ReadMore: Integer;
DummyBytes: DWORD;
Begin
FillChar(IO, SizeOf(IO), 0);
IO.hEvent := FIOEvent;
Bytes := 0;
ReadMore := ToRead; // Сначала 2 байта, потом остальное
Result := ReadFile(idComm, Buf[1], ReadMore, DummyBytes, @IO);
If (Not Result) Then
Begin
If (GetLastError = ERROR_IO_PENDING) Then
Begin
WaitRes := WaitForSingleObject(IO.hEvent, 200);
If WaitRes = WAIT_TIMEOUT Then
OutputDebugString(PChar('Timeout'));
Result := WaitRes = 0;
If (Result) Then
Result := GetOverlappedResult(idComm, IO, Bytes, False);
End Else OutputDebugString(PChar('ReadFile bug'));
End Else Result := GetOverlappedResult(idComm, IO, Bytes, False);
If Not Result Then
OutputDebugString(PChar('Wait bug: ' + SysErrorMessage(GetLastError)));
End;
Ошибок чтения не возникает, результат иногда = 0 байт.
ага0 (2008-05-26 14:26:00) [11]2 REA
Показал бы лучше полный код
REA (2008-05-26 13:16:00) [12]Переделал все примерно как было с начала. Проблема та же: ошибок при чтении и ожидании не возникает, но кадры куда то теряются - GetOverlappedResult возвращает 0 байт (если снова попытаться прочитать ReadFile, то все равно 0 байт и таймаутов никаких не возникает). Т.е. как бы данные есть, но их 0.
REA (2008-05-26 12:55:00) [13]С лишними байтами разобрался - я переделал, чтобы оно читало не заданное количество байт, а все что есть, а по протоколу передатчик может послать сразу несколько кадров, а я про это уже забыл. Придется переделать обратно и добиваться чтобы работало... Причем таймаутов там никаких особых между кадрами нету и желательно чтобы WaitFSO возвращалось после чтения 2х начальных байт, а она этого делать не желает иногда... копаем дальше.
REA (2008-05-26 11:35:00) [14]>Если контрольная сумма совпадает, то это не лишнии байты.
Контрольная сумма совпадает по числу байт из заголовка, остальные не учитываю. Работает нестабильно. Пока не могу сказать еще как - сам не понял.
>Уход последнего байта ловят по TX_EMPTY
Так и ловлю, но мне нужен еще уход последнего бита.
>у тебя всё-таки с указателями, где-то что-то не так
На одном компьютере все так, а на другом не так? Вряд ли...
>Сам усложнил логику (совершенно необосновано) -- сам огрёб.
Без таймаутов порта вообще не работает - не вылезает из WaitFSO. Даже по межбайтовому вылезает не всегда.
DiamondShark (2008-05-23 18:42:00) [15]Редкостное извращение: и таймауты и оверлапед.
Сам усложнил логику (совершенно необосновано) -- сам огрёб.
tesseract (2008-05-23 16:55:00) [16]
> См. выше про DTR и уход последнего бита
Уход последнего байта ловят по TX_EMPTY. Список проблем, позволяет поставить диагноз, что у тебя всё-таки с указателями, где-то что-то не так, и NX срабатывает, или перезаписываешь, что-то не то.
Anatoly Podgoretsky (2008-05-23 16:26:00) [17]> REA (23.05.2008 16:20:58) [58]
Если контрольная сумма совпадает, то это не лишнии байты.
REA (2008-05-23 16:20:00) [18]>А тайминги просто на операции чтения/записи никак проставить ?
См. выше про DTR и уход последнего бита
>Порт зачищай при открытии. Буфер порта, если не изменяет память, при открытии мусор содержит.
Зачищаю при ошибках, но там ошибок то не возникает. Все работает, но байт откуда то иногда берется больше, чем по идее устройство должно посылать. Контрольная сумма совпадает, а что за лишние байты не знаю...
tesseract (2008-05-23 16:08:00) [19]
> Сделал задержку 1мс после записи, чтобы приемник не обрезал
> конец кадра.
А тайминги просто на операции чтения/записи никак проставить ?
> Почему то еще при чтении возвращалось больше байт, чем нужно.
Порт зачищай при открытии. Буфер порта, если не изменяет память, при открытии мусор содержит. По крайней мере , реально ставлкивался.
REA (2008-05-23 15:10:00) [20]Проблема закрыта. Сделал задержку 1мс после записи, чтобы приемник не обрезал конец кадра. Почему то еще при чтении возвращалось больше байт, чем нужно. Не знаю откуда оно их берет, но я это проигнорировал и вроде работает в таком виде.