Правильный подход обмена данных с устройствами через COM-порт. Целостность пакетов и производительность обмена26.02.2018, 23:52. Показов 21582. Ответов 71
Метки нет (Все метки)
Приветствую вас, коллеги!
Хочу с вами посоветоваться, ибо мне кажется, что я делаю это не совсем правильно, либо что-то не учёл... Делаю обмен данными с устройством через COM-порт (RS-232) по алгоритму: послал команду в порт (через .Write(...)), поставил задержку (Threading.Sleep(200)), читаю ответ (через .Read(...)). И вот тут меня смущает эта самая задержка. Если ответные пакеты приходят большие (ну например более 60 байтов), то что бы вычитать весь буфер, этой задержки как буд-то не хватает, пакет получаю не весь. Если увеличиваю задержку, то буфер весь вычитывается, однако, во-первых, буфера могут быть разной длины, и для каждого так подбирать задержки - не реально, во-вторых, если с устройством есть возможность обмениваться на разных скоростях (бод), это вообще дур-дом и всякая актуальность, например, выбора более высокой скорости обмена теряется, т.к. задержки будут одинаковыми, если их так железно задавать... В-третьих, когда такая функция обмена, с железно заданным Sleep'ом (подобранным на вскидку, чтоб не потерять большие пакеты), в цикле, например, ведёт обмен, то для более мелких пакетов, такая задержка, опять же, становится не актуальной, т.к. увеличивается драгоценное время простоя, и обмен происходит дольше, чем мог бы быть... Вот по этому я и задаюсь вопросом: как в таком случае правильно следует поступать? Не ужели чем длиннее ответный пакет, тем дольше его нужно ждать, чтоб он вычитался? Как избежать таких диких задержек? У кого был подобный опыт с обменом по СОМ-порту с устройствами, подскажите, пожалуйста, или поделитесь идеями, кто хотя бы понял суть вопроса. P.S. слышал что-то про подход асинхронного чтения данных из порта, но пока не понял что это и с чем это едят, и мой ли это вообще случай. Если да, то расскажите про такой подход, кто в курсе вообще. Только по понятнее пожалуйста, с примерами, если можно, а то про асинхронные приёмы работы пока вообще не в теме... Особо не доводилось использовать.
0
|
|
| 26.02.2018, 23:52 | |
|
Ответы с готовыми решениями:
71
Организация обмена данными через LPT-порт Функция для обмена HEX данными через COM порт Синхронизация обмена данных через LiFi |
| 07.04.2018, 20:06 [ТС] | |||
.
0
|
|||
| 09.04.2018, 12:59 [ТС] | ||
|
Ну, если я правильно всё понял, то это очень хороший результат!
0
|
||
|
|
|
| 09.04.2018, 13:09 | |
|
AN3155 - USART protocol used in the STM32 bootloader, команда ReadMemory, до 256 байт примерно.
0
|
|
| 09.04.2018, 13:46 [ТС] | ||
|
Not Found Cannot serve request to /content/ccc/resource/technical/document/application_note/51/5f/03/1e/bd/9b/45/be/CD00264342.pdf/ ApacheSling/2.4 (jetty/9.2.9.v20150224, Java HotSpot(TM) 64-Bit Server VM 1.8.0_45, Linux 4.9.85-37.55.amzn1.x86_64 amd64)
0
|
||
|
|
|
| 09.04.2018, 13:50 | |
|
Хм. Вот так http://www.st.com/resource/en/... 264342.pdf
0
|
|
| 09.04.2018, 15:37 [ТС] | ||
|
Вы привели скриншоты с WinAPI. Это вы на нём обмен реализовали, или как? Его как-то в коде C# можно применить?
0
|
||
| 09.04.2018, 16:07 [ТС] | ||
0
|
||
|
|
||||||
| 09.04.2018, 18:54 | ||||||
|
В ЛС от 2018-03-01 11:37 мск.
Попробуйте применить то, что выше советовали: Правильный подход обмена данных с устройствами через COM-порт. Целостность пакетов и производительность обмена Это проще. Добавлено через 8 минут Код мой вам не поможет: весь я показать не могу, а часть - лишь верхушка айсберга. Непосредственно чтение на самом нижнем уровне выглядит так:
0
|
||||||
| 09.04.2018, 21:25 [ТС] | |||
![]() Добавлено через 1 час 48 минут А вот за "рабочие исходники" © был бы признателен! Хочется наглядно посмотреть, как правильно на деле вы применяете методы (и какие именно) этого класса... Особенно интересует метод чтения, а то что-то я его не заметил там...
0
|
|||
|
|
||||||||
| 10.04.2018, 11:20 | ||||||||
Вот нашел исходный код и пересобрал его (см присоединенный файл NETSerialComm.zip). Это COM терминал сделанный поверх CommBase. В нем есть класс BaseTerm который унаследован от CommBase. В нем есть переопределенный метод OnRxChar, который принимает входящие байты. Кроме того я нашел у себя еще один класс SerialClient. Это обертка поверх стандартного SerialPort. Он также работает быстрее стандартного SerialPort. В эттейче - пример (WindowsFormsApplication226.zip - это исходник принимающий данные с камеры, прием данных происходит в событии OnReceiving). Кроме того, этот код публиковался в MSDN Magazine, поэтому думаю с использованием проблем не должно быть.
2
|
||||||||
| 10.04.2018, 12:05 [ТС] | |||
0
|
|||
|
|
||
| 10.04.2018, 13:51 | ||
|
SerialClient - простой в использовании. Но он решает только проблему временных задержек стандартного SerialPort. Если проблема только с задержками - можно попробовать его. CommBase - более сложный. Но он низкоуровневый, на WinAPI, соответственно в нем можно сделать все что хочешь.
0
|
||
| 10.04.2018, 14:20 [ТС] | |
|
0
|
|
| 16.04.2018, 12:43 [ТС] | ||||||
|
Storm23, добрый день! Ещё раз спасибо за эти два отличных примера. Поизучав их на днях, долго не мог решить, каким из них всё же попробовать воспользоваться для изменения алгоритма обмена в своём проекте... Честно, даже до сих пор толком не определился, но думаю попробовать применить второй вариант. В связи с чем у меня появилась парочка вопросов по логике работы вашего примера.
1) Если я правильно понял, то в этой программе вы сначала настраиваете СОМ-порт на определённые настройки, после чего открываем порт и держим его открытым на протяжении всей работы программы? Если, как вы сообщили, эта программа принимает данные с камеры (непрерывно видимо), то это логично. А вот на сколько такой подход целесообразен, если приём данных в программе происходит только тогда, когда пользователь нажмёт соответствующие кнопки и пакеты при этом могут быть как единоразовыми (пакет с посылкой →, ответный пакет ←), так и вида: пакет с посылкой →, цикл ответных пакетов ← ? В моём нынешнем варианте я каждый раз открываю порт перед отправкой пакета в устройство и получением ответа (ответов), а по окончании обмена закрываю. Можно ли оставить такую концепцию, или всё стоит держать порт открытым пока программа запущена? 2) По обмену: опять же, если я всё правильно понял, отправка пакета осуществляется функцией void Transmit(byte[] packet), тайм-ауты приёма по умолчанию отсутствуют вообще (= -1), а для приёма нужно подписываться на событие OnReceiving, таким образом: com.OnReceiving += new EventHandler<RTSerialCom.DataStreamEvent Args>(com_OnReceiving); Всё верно? А в этом событии чтение в отдельном потоке происходит, так? И по этому нет ни тайма-аутов, не слипов? Добавлено через 1 час 49 минут Кстати. Немного доработал вашу функцию bool OpenConn() (в модуле FastSerial): после открытия порта ( _serialPort.Open(); ), добавил очистку буфера приёма/передачи:
0
|
||||||
|
|
||||
| 18.04.2018, 10:22 | ||||
|
0
|
||||
| 18.04.2018, 13:00 [ТС] | |||||||||||
|
Storm23, Ну вроде реализовал данный подход. Но со слипами всё равно какая-то хрень. Для пакетов поменьше хватает и 100мс, а для пакетов побольше приходится подбирать разные (и 200, и 400 и 600)... И как-то не особо стабильно ведёт себя: то успевает за это время задержки принять пакет, то нет... Пока не пойму, но делать большие слипы мне не нравится... Либо я что-то не так делаю?
Добавлено через 1 час 0 минут Storm23, что бы не гадать, я пожалуй покажу, что у меня получилось, а вы может свежим взглядом увидите, что я возможно делаю не правильно. Т.к. мне кажется, я не совсем понял механизм уведомления завершения приёма каждого отдельного ответного пакета. В вашем примере я так понимаю, включаем поток чтения один раз и больше его не перезапускаем, и вертимся в нем, накапливая буфер, и по ходу разбирая его... В своём алгоритме же я каждый раз, перед отправкой команды в устройство, вызываю метод RestartComPort(), тем самым запустив поток чтения, а после принятия ответного пакета в обработчике ответа дёргаю флаг, что пакет полностью принят и закрываю соединение, отписываясь вместе с тем от события обработки чтения... Но вот тут как раз я и не уверен, во-первых в целесообразности такого "передёргивания" порта и сессии чтения)), а во-вторых тут как раз и не совсем понятно, как сообщить из обработчика чтения, что пакет успешно принят, и передать управление коду дальше??? В общем вот мой вариант представления:
0
|
|||||||||||
| 18.04.2018, 19:59 | |
|
Не по теме: Cha1000000,
0
|
|
| 18.04.2018, 21:43 [ТС] | ||
|
Тут бы понять каким образом передавать управление основному потоку из потока чтения, когда посылка считана. Тогда не придётся подбирать слипы наугад... В вашем примере случайно не через Invoke такой механизм осуществляется? Спрашиваю потому, что этим инструментом ещё пользоваться не доводилось и только лишь интуиция мне подсказывает, что возможно именно он для этого и используется...
0
|
||
| 18.04.2018, 21:43 | |
|
Виртуальный COM-порт на STM32, скорость обмена.
COM-порт, работа с двумя формами и одним буфером обмена Запретить вставку текста в TEdit из буфера обмена через Ctrl+V или через контекстное меню Обмена информации через сокеты Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#.
Название изменил на ColorStep.
Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
|
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами:
- ВидТО (СправочникСсылка. ВидыТО);
- ВидГСМ. . .
|
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала.
Ниже прикреплён. . .
|
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F
Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU.
Опрашиваются регистры. . .
|
|
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка:
Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
|
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо
Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
|
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман.
Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
|
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
|