Правильный подход обмена данных с устройствами через COM-порт. Целостность пакетов и производительность обмена26.02.2018, 23:52. Показов 21405. Ответов 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 или через контекстное меню Обмена информации через сокеты Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
| Опции темы | |
|
|
Новые блоги и статьи
|
|||
|
Был там один разговор по поводу свободы в материальном мире.
kumehtar 19.08.2026
Суть: рассматривается живое существо, оказавшееся внутри довольно странной системы (этого мира) и пытающееся обустроить в ней свой кусок пространства.
Жизнь действительно предъявляет каждому. . .
|
Когда логика программы не спасает от человеческих ошибок
Maks 18.08.2026
В последнее время всё чаще и чаще сталкиваюсь с таким явлением, как абсолютная невнимательность (или глупость) пользователей. Проявляется это чаще всего на работе в коллективе. Допустим, человек с. . .
|
Лето уходит
kumehtar 17.08.2026
|
Мысли в слух
kumehtar 17.08.2026
Забавно, насколько сейчас стала доступна информация. Например о магии, духовном развитии, медитациях, и других подобных направлениях, ранее зачастую тайных, передаваемых от учителя к ученику. Хотя. . .
|
|
Перемещение строк из ТЧ в другой документ с учетом текущего пробега
Maks 17.08.2026
Реализация из решения ниже выполнена на примере нетипового документа "Автозапчасти", с ТЧ "Шины".
За основу взят алгоритм отсюда: https:/ / www. cyberforum. ru/ blogs/ 359708/ 10838. html
Задача: . . .
|
Саморегулирующийся социальный контракт для сервера cross-section.
Hrethgir 14.08.2026
С кодом конечно таких глубоких размышлений пока не было, впрочем я уже привык к алгоритмизации. Суть предмета записи: снова в диалоге с нейросетью (я взял пока себе ник для учётки админа - Rector). . . .
|
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет:
1. Использовать системное время и дату,
2. Есть возможность вводить время и дату вручную.
3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
|
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber.
Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
|