Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.99/103: Рейтинг темы: голосов - 103, средняя оценка - 4.99
6 / 5 / 3
Регистрация: 04.06.2015
Сообщений: 250
Записей в блоге: 1

Правильный подход обмена данных с устройствами через COM-порт. Целостность пакетов и производительность обмена

26.02.2018, 23:52. Показов 21331. Ответов 71
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Приветствую вас, коллеги!
Хочу с вами посоветоваться, ибо мне кажется, что я делаю это не совсем правильно, либо что-то не учёл...
Делаю обмен данными с устройством через COM-порт (RS-232) по алгоритму: послал команду в порт (через .Write(...)), поставил задержку (Threading.Sleep(200)), читаю ответ (через .Read(...)). И вот тут меня смущает эта самая задержка. Если ответные пакеты приходят большие (ну например более 60 байтов), то что бы вычитать весь буфер, этой задержки как буд-то не хватает, пакет получаю не весь. Если увеличиваю задержку, то буфер весь вычитывается, однако, во-первых, буфера могут быть разной длины, и для каждого так подбирать задержки - не реально, во-вторых, если с устройством есть возможность обмениваться на разных скоростях (бод), это вообще дур-дом и всякая актуальность, например, выбора более высокой скорости обмена теряется, т.к. задержки будут одинаковыми, если их так железно задавать... В-третьих, когда такая функция обмена, с железно заданным Sleep'ом (подобранным на вскидку, чтоб не потерять большие пакеты), в цикле, например, ведёт обмен, то для более мелких пакетов, такая задержка, опять же, становится не актуальной, т.к. увеличивается драгоценное время простоя, и обмен происходит дольше, чем мог бы быть... Вот по этому я и задаюсь вопросом: как в таком случае правильно следует поступать? Не ужели чем длиннее ответный пакет, тем дольше его нужно ждать, чтоб он вычитался? Как избежать таких диких задержек? У кого был подобный опыт с обменом по СОМ-порту с устройствами, подскажите, пожалуйста, или поделитесь идеями, кто хотя бы понял суть вопроса.

P.S. слышал что-то про подход асинхронного чтения данных из порта, но пока не понял что это и с чем это едят, и мой ли это вообще случай. Если да, то расскажите про такой подход, кто в курсе вообще. Только по понятнее пожалуйста, с примерами, если можно, а то про асинхронные приёмы работы пока вообще не в теме... Особо не доводилось использовать.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
26.02.2018, 23:52
Ответы с готовыми решениями:

Организация обмена данными через LPT-порт
разработайте программу определения адреса LPT - порта и вывода информации через LPT - порт, При этом светодиоды стенда должны отображать: ...

Функция для обмена HEX данными через COM порт
Помогите реализовать функцию работы с COM портом в консольном приложении. Алгоритм такой: Слушаем порт и при появлении HEX команды,...

Синхронизация обмена данных через LiFi
Здравствуйте. Никак не могу придумать способ реализации обмена через свет. Алгоритмом все вроде бы хорошо: "отмигиваем"...

71
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
07.04.2018, 18:54
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Cha1000000 Посмотреть сообщение
я стремлюсь максимально, на сколько это возможно, уменьшить время, за которое будет проходить обмен.
У всех разные цели. Я предпочел стабильность выгадыванию миллисекунд (как-никак, моих пользователей интересует не лишняя миллисекунда времени, а стабильность программы).

Добавлено через 1 минуту
Цитата Сообщение от Rius Посмотреть сообщение
посылки у вас были заранее известного объёма?
Ну да, у меня заранее известный протокол обмена (то есть я всегда знаю, что я отправляю и что должно прийти в ответ на такой запрос).
0
Эксперт .NET
 Аватар для Rius
13377 / 7832 / 1695
Регистрация: 25.05.2015
Сообщений: 23,833
Записей в блоге: 14
07.04.2018, 18:56
insite2012, ну вот, если вы точно знаете, сколько должно прийти байт в ответ, это в корне меняет проблему...
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
07.04.2018, 18:59
Rius, кстати, было бы интересно как-нибудь декомпилировать C-шную библиотеку для обмена и посмотреть, как там это реализовано. Я вот сейчас пишу программу, но там весь обмен как раз в C-шной либе скрыт, а я только через импортом пользуюсь методами оттуда.

Добавлено через 1 минуту
Цитата Сообщение от Rius Посмотреть сообщение
точно знаете, сколько должно прийти байт в ответ
Да, знаю. Но вот когда они придут (и придут ли все сразу, или кусками, или не придут вообще)-в том и проблема. И естественно, что, например, через живой COM ответ придет в разы быстрее, чем по БТ каналу. Потому и проходилось мудрить...
0
Эксперт .NET
 Аватар для Rius
13377 / 7832 / 1695
Регистрация: 25.05.2015
Сообщений: 23,833
Записей в блоге: 14
07.04.2018, 19:00
Если библиотека сделана по канонам, то скорее всего оно описано в известном документе Serial Communication in Win32.

Добавлено через 1 минуту
Цитата Сообщение от insite2012 Посмотреть сообщение
Да, знаю. Но вот когда они придут (и придут ли все сразу, или кусками, или не придут вообще)-в том и проблема. И естественно, что, например, через живой COM ответ придет в разы быстрее, чем по БТ каналу. Потому и проходилось мудрить...
А как минимизировать время ожидания, если байты так и не пришли? Подсчитывать время от начала ожидания в цикле?
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
07.04.2018, 19:05
Цитата Сообщение от Rius Посмотреть сообщение
скорее всего оно описано в известном документе
Так-то да, но там тоже свой, жестко определенный протокол обмена. И вот как они реализовали его там-пока вопрос.
Хотя он больше для интереса, в общем я просто беру и использую импорт из тех либ.

Добавлено через 1 минуту
Цитата Сообщение от Rius Посмотреть сообщение
как минимизировать время ожидания, если байты так и не пришли?
Rius, мы вроде это обсуждали в какой-то теме, и я там даже выкладывал несколько своих вариантов реализации. У меня исходников не осталось (тогда я Гитом еще не пользовался), может вы вспомните ту тему?
0
Эксперт .NET
 Аватар для Rius
13377 / 7832 / 1695
Регистрация: 25.05.2015
Сообщений: 23,833
Записей в блоге: 14
07.04.2018, 19:09
Чтение из COM-порта, странная ошибка ?

Добавлено через 2 минуты
Мне всё это пришлось выдумывать из-за приборов с HART, которые работают на 1200 бодах. Если пакет в ответ не пришёл, напрасно потрачена секунда или две. А если надо проверить наличие 15-ти приборов на линии, это ппц...
0
6 / 5 / 3
Регистрация: 04.06.2015
Сообщений: 250
Записей в блоге: 1
07.04.2018, 19:13  [ТС]
Цитата Сообщение от insite2012 Посмотреть сообщение
У всех разные цели. Я предпочел стабильность выгадыванию миллисекунд (как-никак, моих пользователей интересует не лишняя миллисекунда времени, а стабильность программы).
Ну да, не зная подробностей целей, может показаться, что это не столько важно и не над чем тут заморачиваться... Но, для лучшего понимания идеи и целей, кратко опишу суть.
У моей программы, общающейся с устройством, есть как одиночные команды, с одиночными ответными буферами на них, так и команды-запросы, на которые устройство циклом в 500, 2000, и даже 11000 итераций выдаёт данные, ну скажем, по 180-250 байт за одну итерацию. И вот когда пользователю нужно считать из устройства его базу, например, в 6000, или тем более в 11000 (это пока максимум) полей (строк), раньше в алгоритме обмена со слипом, это занимало около 40 минут... +/-
А вот с методом двух тайм-аутов это время уже сократилось до 5 минут (тоже примерно. точно сейчас не припомню). Но при этом методе, как уже неоднократно упоминал, на ПК разных мощностей, эти показатели разнятся...
В общем в моём случае, пользователям (хотя скорее больше моему начальству) не особо хочется долго ждать выполнения чтения столь не малого кол-ва данных. Особенно, если за время работы с программой, это нужно повторять неоднократно...
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
07.04.2018, 19:15
Rius, нет, значит не там... Там всего один вариант, а я точно помню, что экспериментировал по разному. Сейчас залез в исходники, остался только метод с комментом Вариант №1, остальные я стер. Попробую поискать, точно помню, что как минимум три варианта было. И да, ваш вариант я пробовал. Он работает побыстрее чем мой, но опять же, нет той стабильности. А мне это важно, мне за это деньги платят)))
0
Эксперт .NET
 Аватар для Rius
13377 / 7832 / 1695
Регистрация: 25.05.2015
Сообщений: 23,833
Записей в блоге: 14
07.04.2018, 19:16
Cha1000000, а объём посылки, которая должна прийти в ответ на запрос, вам заранее известен?
0
6 / 5 / 3
Регистрация: 04.06.2015
Сообщений: 250
Записей в блоге: 1
07.04.2018, 19:22  [ТС]
Цитата Сообщение от Rius Посмотреть сообщение
а объём посылки, которая должна прийти в ответ на запрос, вам заранее известен?
Да, у меня так же, как и у insite2012 , работа программы осуществляется по чёткому протоколу обмена. В котором на каждую команду прописано какой длины будет ответ.
И в принципе, согласно протоколу, в ответной посылке на все команды, второй байт - это и есть длина пакета.
0
Эксперт .NET
 Аватар для Rius
13377 / 7832 / 1695
Регистрация: 25.05.2015
Сообщений: 23,833
Записей в блоге: 14
07.04.2018, 19:23
Cha1000000, тогда попробуйте, что говорит insite2012.
Я принципиально рассчитываю на неизвестную длину пакета, что в прогах на МК, что на ПК. А это немного иное.
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
07.04.2018, 19:25
Rius, да, кстати, вот кусок кода из промышленной либы (на шарпе, которая использует импорт). Как видите, при работе с портом многие не гнушаются использованием слипов)))
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public virtual ProtocolResult ReadWithAttempts(bool high_byte_first, uint ui32Address, ushort ui16Size, ref byte[] pui8Buffer, CommandCode BankAndFlags, bool enable_sector_select, ref ushort curr_sector_idx) {
            for (int i = 0; i < 4; i++) {
                if (BankAndFlags != CommandCode.BANK_0) {
                    if (DaasAPI.SendExternalRead(this.m_i16PortNr, ui32Address, ui16Size, ref pui8Buffer, BankAndFlags) == GeneralResult.DAAS_OK) {
                        return ProtocolResult.OK;
                    }
                    Thread.Sleep(70);
                }
                else if (enable_sector_select) {
                    if (this.memory_reader.Read(this.m_i16PortNr, ui32Address, ui16Size, ref pui8Buffer, ref curr_sector_idx, high_byte_first)) {
                        return ProtocolResult.OK;
                    }
                }
                else {
                    if (DaasAPI.SendRead(this.m_i16PortNr, ui32Address, ui16Size, ref pui8Buffer) == GeneralResult.DAAS_OK) {
                        return ProtocolResult.OK;
                    }
                    Thread.Sleep(70);
                }
            }
            return ProtocolResult.READ_ERROR;
        }
0
Эксперт .NET
 Аватар для Rius
13377 / 7832 / 1695
Регистрация: 25.05.2015
Сообщений: 23,833
Записей в блоге: 14
07.04.2018, 19:28
Цитата Сообщение от insite2012 Посмотреть сообщение
из промышленной либы ... при работе с портом многие не гнушаются
Тут где-то показывали код из программы для трейдинга на бирже, то ли очень популярной, то ли от очень крутой фирмы. И там - лютый говнокод. Так что, это не показатель
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
07.04.2018, 19:33
Цитата Сообщение от Rius Посмотреть сообщение
это не показатель
Это понятно. Но просто надо четко понимать цель: одно дело, когда пишешь для себя, исследуешь что-то и другое, когда пишешь для массового применения. Естественно, во втором случае мы просто физически не сможем проверить программу на множестве вариантов конфигураций ПК, где она, возможно, будет применяться. Поэтому приходится чем-то жертвовать, идти на компромиссы ради стабильности программы.
0
07.04.2018, 19:35

Не по теме:

Цитата Сообщение от insite2012 Посмотреть сообщение
кусок кода из промышленной либы
Ога, я тоже сталкивался с "примышленными либами". Такого ужаса еще поискать. Качество ниже плинтуса, и кучи (не просто кучи, а КУЧИ) слипов. Я думаю это связано с тем, что железятники - обычно не программисты и пишется это ПО на коленке, абы було.

0
6 / 5 / 3
Регистрация: 04.06.2015
Сообщений: 250
Записей в блоге: 1
07.04.2018, 19:38  [ТС]
Цитата Сообщение от insite2012 Посмотреть сообщение
Поэтому приходится чем-то жертвовать, идти на компромиссы ради стабильности программы.
Вот и я это пытаюсь начальству объяснить... Но они что-то пока в скорость упёрлись и всё тут... Типа у конкурентов аналогичное устройство "за 2 (или 5) минут выгружает базу в 20000 строк" со слов начальника...
0
Эксперт .NET
 Аватар для Rius
13377 / 7832 / 1695
Регистрация: 25.05.2015
Сообщений: 23,833
Записей в блоге: 14
07.04.2018, 19:41
insite2012, да я только за. Пусть ТС пробует по-вашему. С известным размером пакета сам бог велел.

Цитата Сообщение от Storm23 Посмотреть сообщение
что железятники - обычно не программисты
Да, у железячников свой, особый взгляд на программирование. Заточенный на железо. В работе десктопных ОС им в большинстве своём разбираться некогда и незачем. Вот и получается то, что получается.
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
07.04.2018, 19:49
Cha1000000, вы все-таки попробуйте для начала просто подход, цикл в 10 итераций с задержкой по 50 мс и проверкой буфера порта при каждой итерации. В принципе, это должно работать как и обычный таймаут в 500 мс для порта.
Типа того что ниже. И потом уже посмотрите, насколько дольше это работает.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
protected override byte[] GetResponse(byte[] request, int bytesToRead, int requestCount = 3, int milliseconds = 0) {
            //Внешний цикл отправки запроса
            for (int i = 0; i < requestCount; i++) {
                //Очистка буферов порта
                port.DiscardInBuffer();
                port.DiscardOutBuffer();
 
                //Отправка полного блока в порт для записи
                port.Write(request, 0, request.Length);
 
                //Внутренний цикл ожидания данных в буфере порта
                for (int j = 0; j < 10; j++) {
                    Thread.Sleep(70);
                    if (port.BytesToRead == bytesToRead) {
                        byte[] response = new byte[bytesToRead];
                        port.Read(response, 0, bytesToRead);
                        return response;
                    }
                }
            }
            return null;
        }
Добавлено через 5 минут
Цитата Сообщение от Rius Посмотреть сообщение
Вот и получается то, что получается.
Ну да, та программа, кусок кода из которой я показал, в плане работы с железом (мк) просто удивительна. Сделана очень хорошо и со знанием дела (я бы так не смог, нужны хорошие знания работы с мк, коими я не обладаю). А вот в плане интерфейса-это просто тихий ужас. Если без подробностей-разработчики попытались сделать нечто вроде а-ля WPF, но все это на формах, да еще и на 2-м .NET-е. Жесть конечно вышла та еще, косяков куча (с размерами окон, не влезающими надписями и прочим).
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10428 / 5158 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
07.04.2018, 19:50
Цитата Сообщение от Cha1000000 Посмотреть сообщение
Типа у конкурентов аналогичное устройство "за 2 (или 5) минут выгружает базу в 20000 строк" со слов начальника...
Не знаю поможет вам или нет в вашей проблеме, но я когда-то тоже сталкивался с медленной работой COM порта, и выяснилось, что это проблема дотнетовского SerialPort. После этого я всегда использовал другой сериал порт, вот типа такого https://github.com/AnthonyNyst... ommBase.cs
Он работает значительно быстрее (если по ссылке не разберетесь могу скинуть рабочие исходники).
2
Эксперт .NET
 Аватар для Rius
13377 / 7832 / 1695
Регистрация: 25.05.2015
Сообщений: 23,833
Записей в блоге: 14
07.04.2018, 19:57
Цитата Сообщение от Storm23 Посмотреть сообщение
другой сериал порт
Обёртка над тем самым трушным WinAPI.
Жаль лицензия не указана.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
07.04.2018, 19:57

Виртуальный COM-порт на STM32, скорость обмена.
Всем привет. Прошу помощи :) Экспериментирую с USB - CDC-класс, стоит задача передать данные в хост на максимально возможной скорости....

Копирование через буфер обмена из 2х полей формы и вставка данных в другую форму
Всем очень добрый день! Подскажите пожалуйста, можно ли реализовать одновременное копирование данных из 2-х полей формы и вставку этих...

COM-порт, работа с двумя формами и одним буфером обмена
Доброго времени суток. Обращаюсь с вопросом, который повторяли, наверно, сотню и один раз. Но ответа, подходящего под специфическую...

Запретить вставку текста в TEdit из буфера обмена через Ctrl+V или через контекстное меню
Добрый день! Есть такой вопрос: Что нужно сделать, чтобы в TEdit не было возможности вставить текст из буфера обмена при помощи CTRL+V...

Обмена информации через сокеты
Здравствуйте, уважаемые форумчани. Пожалуйста, помоги сделать эту задачу: В среде Visual C++ написать клиентскую и серверную программы...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
сукцессия 31: модель микоризы - это модель ещё нескольких явлений, социальных и экономических
anaschu 18.07.2026
Теория «Всего»: апдейт v1. 1. 2 — 28‑мерное ядро стабилизировано Коллеги, фиксирую разбор инженерных правок и их изоморфную проекцию на экономику, меметику и половой отбор. Модель теперь не. . .
сукцессия 30. Массив проверяющих друг друга моделей
anaschu 18.07.2026
Архитектура сети взаимопроверяющих моделей микоризной сукцессии (v2. 0) Развитие тензорного ОДУ-ядра и создание кросс-платформенного калибровочного полигона Уважаемые коллеги! В продолжение. . .
Грибы - это женщины, деревья - это мужчины. Анти инь янь для союза мужчины и женщины.
anaschu 18.07.2026
ГЛАВНЫЙ НАУЧНО-ФИЛОСОФСКИЙ ВЫВОД: Сексуально-Репродуктивный Капитализм против Государства Моногамии Коллеги, мы вышли на финишную прямую 20-мерного ОДУ-моделирования вековой сукцессии (ветка. . .
Текстовый слайдер с нумерацией страниц и кроссбраузерность.
russiannick 18.07.2026
Один мой друг написал текстовый слайдер с нумерацией страниц. Сегодня я расскажу как он умудрился подружить его с кроссбраузерностью. Очевидно сложно угодить с шириной каждому браузеру. Один крадет. . .
Грибы - это мемы, дерево - это человек. Применение микоризной модели к теории меметики Докинза.
anaschu 18.07.2026
Меметический изоморфизм теории «всего»: Грибная сукцессия как модель эволюции идей Докинза Базовый код системы ОДУ микоризной сукцессии описывает не просто биологию, а универсальную. . .
Грибы - это корпорации, деревья - это государства. Механизм массонского захвата власти
anaschu 18.07.2026
Макроэкономический изоморфизм теории «всего»: Грибная сукцессия как модель транснационального капитализма Базовый код системы ОДУ микоризной сукцессии описывает не просто биологию, а. . .
Расчёт периметра прямоугольника по координатам вершин
Maks 18.07.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Вычислить периметр прямоугольника, заданного координатами своих вершин на плоскости. Решение: Создан документ со следующими. . .
Подсчёт частоты трёхбуквенных слов в тексте
Maks 18.07.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Выясните, сколько раз в предложенном тексте встречается каждое трехбуквенное слово. Решение: Создан документ с единственным. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru