-
> См. выше про DTR и уход последнего бита
Уход последнего байта ловят по TX_EMPTY. Список проблем, позволяет поставить диагноз, что у тебя всё-таки с указателями, где-то что-то не так, и NX срабатывает, или перезаписываешь, что-то не то.
-
Редкостное извращение: и таймауты и оверлапед. Сам усложнил логику (совершенно необосновано) -- сам огрёб.
-
>Если контрольная сумма совпадает, то это не лишнии байты. Контрольная сумма совпадает по числу байт из заголовка, остальные не учитываю. Работает нестабильно. Пока не могу сказать еще как - сам не понял.
>Уход последнего байта ловят по TX_EMPTY Так и ловлю, но мне нужен еще уход последнего бита.
>у тебя всё-таки с указателями, где-то что-то не так На одном компьютере все так, а на другом не так? Вряд ли...
>Сам усложнил логику (совершенно необосновано) -- сам огрёб. Без таймаутов порта вообще не работает - не вылезает из WaitFSO. Даже по межбайтовому вылезает не всегда.
-
С лишними байтами разобрался - я переделал, чтобы оно читало не заданное количество байт, а все что есть, а по протоколу передатчик может послать сразу несколько кадров, а я про это уже забыл. Придется переделать обратно и добиваться чтобы работало... Причем таймаутов там никаких особых между кадрами нету и желательно чтобы WaitFSO возвращалось после чтения 2х начальных байт, а она этого делать не желает иногда... копаем дальше.
-
Переделал все примерно как было с начала. Проблема та же: ошибок при чтении и ожидании не возникает, но кадры куда то теряются - GetOverlappedResult возвращает 0 байт (если снова попытаться прочитать ReadFile, то все равно 0 байт и таймаутов никаких не возникает). Т.е. как бы данные есть, но их 0.
-
2 REA
Показал бы лучше полный код
-
Сейчас локальная функция чтения выглядит так:
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 байт.
-
> IO.hEvent := FIOEvent;
Лучше событие пересоздавать. А то при многопоточности, ерунда может выйти.
-
Ну и иде настройка порта? Я почему спрашиваю-та - ежель
> ошибок при чтении и ожидании не возникает, но кадры куда > то теряются - GetOverlappedResult возвращает 0 байт (если > снова попытаться прочитать ReadFile, то все равно 0 байт > и таймаутов никаких не возникает). Т.е. как бы данные есть, > но их 0.
то возможно чтение завершается по таймауту порта, тыж статус порта не проверяешь
-
>Лучше событие пересоздавать. А то при многопоточности, ерунда может выйти.
Пробовал, то же самое.
>Ну и иде настройка порта? Я почему спрашиваю-та - ежель
Уж какие я только не ставил вариации из таймаутов. Межбайтовый таймаут особенно не влияет на результат, а вот общий таймаут на чтение, если не поставить, то иногда будет подвисать в WaitFSO. Сейчас стоит межбайтовый 1мс и общий 50 мс. Действительно, в мониторе на операции чтения написано сейчас TIMEOUT, но откуда бы ему взяться? Если читать одним куском, а не как сейчас в два захода, то все работало. кажется...
-
> то все работало. кажется...
Креститься надо, када кажется:) Шютка, не обижайся. Ежель неуверенно чуйствуешь себе в таймаутах порта, то есть железный способ - отключить их нафиг. Далее ставишь маску эвентов SetCommEvent ждешь прихода байтов асинхронным вызовом WaitCommEvent с ...WaitFor... и нужным по логике приложения таймаутом или бесконечно. На срабатывание делаешь GetOverlappedResult и смотришь маску, которую передавал в WaitCommEvent. Ежель там EV_RXCHAR, вызываешь ReadFile и читаешь либо все, что пришло, либо сколько нужно до полного пакета. Далее цикл по новой - WaitCommEvent etc. Набрав целый пакет, вызываешь его обработку. Способ железобетонный, когда девайс шлет не шибко периодично, то пусто то густо. Если пакеты идут с хорошей периодичностью, то да, таймауты порта удобны, а иначе - ну их нахвиг.
-
> Ежель там EV_RXCHAR, вызываешь ReadFile
Вызываешь ClearComError - смотришь сколько пришло. Таймауты порта на старом железе и при хорошей длине кабеля - вещь важная.
-
>Ежель неуверенно чуйствуешь себе в таймаутах порта, то есть железный способ - отключить их нафиг.
Без них не работает в таком виде как сейчас. Неуверенно чувствую, потому что результаты получаются непредсказуемые. В принципе можно и так сделать, как ты описал, но проще сделать самому тогда уж буферизацию и читать одним куском с выходом из чтения по таймауту. Но медленнее будет. Хотя в этом случае придется и логику программы переделывать... Пакеты идут сильно периодично - практически всегда, когда не передаются данные.
>Вызываешь ClearComError - смотришь сколько пришло. Таймауты порта на старом железе и при хорошей длине кабеля - вещь важная.
Железо нормальное хоть и самодельное. Кабель тоже не длинный - метра 3-4. Попробую ClearComError еще, но сдается мне монитор правильно показывает.
-
> Без них не работает в таком виде как сейчас
Естессно, нать как я писал.
> то иногда будет подвисать в WaitFSO.
Вот те и ответ - есть дыры между посылками. Неча читать она и висит. А ставишь таймаут - она по нему выкидыват. Тут ты ноль и читашь. Тут прынцип какой - не дергаться без нужды. Пришли байтики - читаем, нет - сопим в тряпочку то бишь спим. Вынеси всю эту беду в отдельный поток пусть се спит скока влезет. Можь ваще там синхронно читать, поставить таймаут милисек 500 - Terminate проверять и все дела. Хотя по мне асинхронка удобней даж в отдельном потоке, управляемость выше.
> Межбайтовый таймаут особенно не влияет на результат
Ты чет иль путаешь иль оценивашь результат. Должны влиять. Если канечна я чего по склерозности не путал:) Давай, кажи таймауты и описалово протокола. Будет время помедитирую.
-
>Вынеси всю эту беду в отдельный поток пусть се спит скока влезет.
так и есть
>Можь ваще там синхронно читать, поставить таймаут милисек 500 Так и было - см. выше. А похоже оно и в синхронном режиме кадры теряет, т.е. может проблема еще и в самой железке.
>Давай, кажи таймауты и описалово протокола. Он длинный. Подобие SDLC
-
Удалено модератором Примечание: Задай вопрос в своей ветке
|