Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2010.03.28;
Скачать: [xml.tar.bz2];

Вниз

COM порт, асинхронные чтение запись   Найти похожие ветки 

 
REA   (2008-05-19 14:36) [40]

Так я же его открываю как CreateFile. А как тогда узнать, сколько байт реально прочиталось?


 
REA   (2008-05-19 14:38) [41]

А, в смысле DeviceIOControl только к файлам относится... А то можно двояко прочитать.


 
Сергей М. ©   (2008-05-19 14:41) [42]


> я же его открываю как CreateFile


И что ?

Первым параметром ты указал "COMn", следовательно, требуешь от системы работу с этим файлом как с файлом коммуникационного дивайса ..


 
REA   (2008-05-19 15:01) [43]

Вот нашел - может иметь отношение к теме. А может и не иметь...
http://support.microsoft.com/kb/q184072/

Пробовал сделать через макрос HasOverlappedIoCompleted. Как то не то...


 
Evgeny V ©   (2008-05-19 15:02) [44]


> REA   (19.05.08 14:36) [40]

Отвечая на вопрос -сколько байт и когда читать, а также  для удобной работы с портом посмотри следующие функции
WaitCommEvent - ждем нужных событий,
SetCommMask - подписаться на нужные нам события.
ClearCommError -  обрати внимание на стурктуру COMSTAST и поле cbInQue.


 
REA   (2008-05-19 15:31) [45]

А разница между "короткими" и "длинными" кадрами объсняется просто - при коротких кадрах WaitForSingleObject попросту не вызывается (ReadFile возвращает True) и все работает. Как только доходит до WaitForSingleObject работает через раз.


 
REA   (2008-05-19 15:44) [46]

Переделал чтение "одним куском" с прекращением по межбайтовому таймауту. Работать стало несколько стабильнее, хотя таймауты Wait по прежнему иногда возникают.


 
VICTOR_   (2008-05-19 15:48) [47]

Есть чудная статья на "Королевство Дельфи"
http://www.delphikingdom.com/asp/articles_forum.asp?ArticleID=1126
Реализовывал на ее основе приложение (чтение сигнала из COM-порта) - все работало корректно. Данные не терялись.  
В процессе отладки также использовал программу Portmon


 
REA   (2008-05-19 16:01) [48]

Еще одна странность: вызов функции CancelIO в случае возникновения таймаута приводит к Acess Violation. Это вообще странно для API функции.


 
Сергей М. ©   (2008-05-19 16:33) [49]


> Это вообще странно для API функции.
>


Похоже что у тебя просто ошибка в 17-й строке, и система тут ни причем)


 
REA   (2008-05-19 18:16) [50]

Почитал статью - принципиально только то, что они сначала дожидаются прихода хотя бы одного байта и потом вызывают ReadFile тем самым пытаясь исключить как я понял злополучной WaitForSingleObject. Но тоже без гарантии...


 
REA   (2008-05-19 18:17) [51]

>Похоже что у тебя просто ошибка в 17-й строке, и система тут ни причем)

Это то и неприятно :( Убрал CancelIO, ошибка пропала. Попробовал сделать с WaitCommEvent перед ReadFile - тоже ничего не получается хорошего


 
VICTOR_   (2008-05-19 19:57) [52]


> Почитал статью - принципиально только то, что они сначала
> дожидаются прихода хотя бы одного байта и потом вызывают
> ReadFile тем самым пытаясь исключить как я понял злополучной
> WaitForSingleObject. Но тоже без гарантии...

Я не знаю какую гарантию Вы хочете получить, так как Вы не описали полностью свою задачу.
Реально приложение, базирующееся на данном примере работает система
- чтение данных из компорта (~12байт) - код карточки
- работа 24*365
- срок реальной эксплуатации 9 мес.
- среднее количество считываний при максимальной загрузке - 20 в мин.
- использование данного приложения как COM-сервера(результат считывания возвращается в родительское приложение)
- на компьютере также крутится серверное приложение и MS SQL Server

Ассинхронный режим выбран в первую очередь  по причинам, описанным в статье - нет реальной нагрузки на процессор и в то же время гарантированно считывается сигнал


 
REA   (2008-05-19 20:05) [53]

Похоже проблема решена:
установил общий таймаут на чтение ReadTotalTimeoutConstant = 100 и видимо когда ReadFile не может завершить чтение по межбайтовому таймауту он завершает по общему таймауту. В итоге таймаута WaitForSingleObject не возникает. Байты все на месте.


 
REA   (2008-05-19 20:08) [54]

>среднее количество считываний при максимальной загрузке - 20 в мин.

Я думаю у меня столько же, но в секунду... Работает 12 лет на разных операционках 24 часа в сутки 365 дней в году, параллельно можно играть в Doom :)


 
REA   (2008-05-23 12:55) [55]

История продолжается: на одном компьютере все работает, а на другом выдает, что считано 0 байт, таймаутов не возникает, но после этого уже ничего читать не желает (всегда 0 байт).


 
REA   (2008-05-23 15:10) [56]

Проблема закрыта. Сделал задержку 1мс после записи, чтобы приемник не обрезал конец кадра. Почему то еще при чтении возвращалось больше байт, чем нужно. Не знаю откуда оно их берет, но я это проигнорировал и вроде работает в таком виде.


 
tesseract ©   (2008-05-23 16:08) [57]


> Сделал задержку 1мс после записи, чтобы приемник не обрезал
> конец кадра.


А тайминги просто на операции чтения/записи никак проставить ?


> Почему то еще при чтении возвращалось больше байт, чем нужно.


Порт зачищай при открытии. Буфер порта, если не изменяет память, при открытии мусор содержит. По крайней мере , реально ставлкивался.


 
REA   (2008-05-23 16:20) [58]

>А тайминги просто на операции чтения/записи никак проставить ?
См. выше про DTR и уход последнего бита

>Порт зачищай при открытии. Буфер порта, если не изменяет память, при открытии мусор содержит.

Зачищаю при ошибках, но там ошибок то не возникает. Все работает, но байт откуда то иногда берется больше, чем по идее устройство должно посылать. Контрольная сумма совпадает, а что за лишние байты не знаю...


 
Anatoly Podgoretsky ©   (2008-05-23 16:26) [59]

> REA  (23.05.2008 16:20:58)  [58]

Если контрольная сумма совпадает, то это не лишнии байты.


 
tesseract ©   (2008-05-23 16:55) [60]


> См. выше про DTR и уход последнего бита


Уход последнего байта ловят по TX_EMPTY.  Список проблем, позволяет поставить диагноз, что у тебя всё-таки с указателями, где-то что-то не так, и NX  срабатывает, или перезаписываешь, что-то не то.


 
DiamondShark ©   (2008-05-23 18:42) [61]

Редкостное извращение: и таймауты и оверлапед.
Сам усложнил логику (совершенно необосновано) -- сам огрёб.


 
REA   (2008-05-26 11:35) [62]

>Если контрольная сумма совпадает, то это не лишнии байты.
Контрольная сумма совпадает по числу байт из заголовка, остальные не учитываю. Работает нестабильно. Пока не могу сказать еще как - сам не понял.

>Уход последнего байта ловят по TX_EMPTY
Так и ловлю, но мне нужен еще уход последнего бита.

>у тебя всё-таки с указателями, где-то что-то не так
На одном компьютере все так, а на другом не так? Вряд ли...

>Сам усложнил логику (совершенно необосновано) -- сам огрёб.
Без таймаутов порта вообще не работает - не вылезает из WaitFSO. Даже по межбайтовому вылезает не всегда.


 
REA   (2008-05-26 12:55) [63]

С лишними байтами разобрался - я переделал, чтобы оно читало не заданное количество байт, а все что есть, а по протоколу передатчик может послать сразу несколько кадров, а я про это уже забыл. Придется переделать обратно и добиваться чтобы работало... Причем таймаутов там никаких особых между кадрами нету и желательно чтобы WaitFSO возвращалось после чтения 2х начальных байт, а она этого делать не желает иногда... копаем дальше.


 
REA   (2008-05-26 13:16) [64]

Переделал все примерно как было с начала. Проблема та же: ошибок при чтении и ожидании не возникает, но кадры куда то теряются - GetOverlappedResult возвращает 0 байт (если снова попытаться прочитать ReadFile, то все равно 0 байт и таймаутов никаких не возникает). Т.е. как бы данные есть, но их 0.


 
ага0   (2008-05-26 14:26) [65]

2 REA

Показал бы лучше полный код


 
REA   (2008-05-26 14:44) [66]

Сейчас локальная функция чтения выглядит так:

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 байт.


 
tesseract ©   (2008-05-26 15:30) [67]


>  IO.hEvent := FIOEvent;


Лучше событие пересоздавать. А то при многопоточности, ерунда может выйти.


 
ага0   (2008-05-26 15:54) [68]

Ну и иде настройка порта? Я почему спрашиваю-та - ежель

> ошибок при чтении и ожидании не возникает, но кадры куда
> то теряются - GetOverlappedResult возвращает 0 байт (если
> снова попытаться прочитать ReadFile, то все равно 0 байт
> и таймаутов никаких не возникает). Т.е. как бы данные есть,
>  но их 0.

то возможно чтение завершается по таймауту порта, тыж статус порта не проверяешь


 
REA   (2008-05-26 17:53) [69]

>Лучше событие пересоздавать. А то при многопоточности, ерунда может выйти.

Пробовал, то же самое.

>Ну и иде настройка порта? Я почему спрашиваю-та - ежель

Уж какие я только не ставил вариации из таймаутов. Межбайтовый таймаут особенно не влияет на результат, а вот общий таймаут на чтение, если не поставить, то иногда будет подвисать в WaitFSO.
Сейчас стоит межбайтовый 1мс и общий 50 мс.
Действительно, в мониторе на операции чтения написано сейчас TIMEOUT, но откуда бы ему взяться? Если читать одним куском, а не как сейчас в два захода, то все работало. кажется...


 
ага0   (2008-05-26 18:25) [70]


> то все работало. кажется...

Креститься надо, када кажется:) Шютка, не обижайся. Ежель неуверенно чуйствуешь себе в таймаутах порта, то есть железный способ - отключить их нафиг. Далее ставишь маску эвентов SetCommEvent ждешь прихода байтов асинхронным вызовом WaitCommEvent с ...WaitFor... и нужным по логике приложения таймаутом или бесконечно. На срабатывание делаешь GetOverlappedResult и смотришь маску, которую передавал в WaitCommEvent. Ежель там EV_RXCHAR, вызываешь ReadFile и читаешь либо все, что пришло, либо сколько нужно до полного пакета. Далее цикл по новой - WaitCommEvent etc. Набрав целый пакет, вызываешь его обработку. Способ железобетонный, когда девайс шлет не шибко периодично, то пусто то густо. Если пакеты идут с хорошей периодичностью, то да, таймауты порта удобны, а иначе - ну их нахвиг.


 
tesseract ©   (2008-05-26 21:44) [71]


> Ежель там EV_RXCHAR, вызываешь ReadFile


Вызываешь ClearComError - смотришь сколько пришло. Таймауты порта на старом железе и при хорошей длине кабеля - вещь важная.


 
REA   (2008-05-27 10:05) [72]

>Ежель неуверенно чуйствуешь себе в таймаутах порта, то есть железный способ - отключить их нафиг.

Без них не работает в таком виде как сейчас. Неуверенно чувствую, потому что результаты получаются непредсказуемые. В принципе можно и так сделать, как ты описал, но проще сделать самому тогда уж буферизацию и читать одним куском с выходом из чтения по таймауту. Но медленнее будет. Хотя в этом случае придется и логику программы переделывать...
Пакеты идут сильно периодично - практически всегда, когда не передаются данные.

>Вызываешь ClearComError - смотришь сколько пришло. Таймауты порта на старом железе и при хорошей длине кабеля - вещь важная.

Железо нормальное хоть и самодельное. Кабель тоже не длинный - метра 3-4. Попробую ClearComError еще, но сдается мне монитор правильно показывает.


 
ага0   (2008-05-27 12:05) [73]


> Без них не работает в таком виде как сейчас

Естессно, нать как я писал.

> то иногда будет подвисать в WaitFSO.

Вот те и ответ - есть дыры между посылками. Неча читать она и висит. А ставишь таймаут - она по нему выкидыват. Тут ты ноль и читашь. Тут прынцип какой - не дергаться без нужды. Пришли байтики - читаем, нет - сопим в тряпочку то бишь спим. Вынеси всю эту беду в отдельный поток пусть се спит скока влезет. Можь ваще там синхронно читать, поставить таймаут милисек 500 - Terminate проверять и все дела. Хотя по мне асинхронка удобней даж в отдельном потоке, управляемость выше.

> Межбайтовый таймаут особенно не влияет на результат

Ты чет иль путаешь иль оценивашь результат. Должны влиять. Если канечна я чего по склерозности не путал:) Давай, кажи таймауты и описалово протокола. Будет время помедитирую.


 
REA   (2008-05-27 15:21) [74]

>Вынеси всю эту беду в отдельный поток пусть се спит скока влезет.

так и есть

>Можь ваще там синхронно читать, поставить таймаут милисек 500
Так и было - см. выше. А похоже оно и в синхронном режиме кадры теряет, т.е. может проблема еще и в самой железке.

>Давай, кажи таймауты и описалово протокола.
Он длинный. Подобие SDLC


 
JUDAS   (2009-01-11 16:52) [75]

Удалено модератором
Примечание: Задай вопрос в своей ветке



Страницы: 1 2 вся ветка

Форум: "WinAPI";
Текущий архив: 2010.03.28;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.61 MB
Время: 0.01 c
3-1237110214
Den
2009-03-15 12:43
2010.03.28
Как узнать номер добавленной записи


4-1231749793
kalexi
2009-01-12 11:43
2010.03.28
Как узнать место расоложения папки "Автозагрузка"?


1-1247504656
Дмитрий Белькевич
2009-07-13 21:04
2010.03.28
Особенности при работе с com портом в dll.


15-1262976243
Германн
2010-01-08 21:44
2010.03.28
Sippoint Mini


2-1264583093
ИгорУЛЬКА
2010-01-27 12:04
2010.03.28
Получить отдельные значения строки





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский