|
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
|
|||||||||||
И снова работа с COM портом16.11.2016, 14:03. Показов 12376. Ответов 67
Метки нет (Все метки)
Приветствую всех. Уже измучился и измаялся весь пытаясь написать функцию. Помогите, пожалуйста...
Описание задачи Создается программа для работы с прибором. Соединение с прибором осуществляется посредством преобразователей, которые при подключении к компьютеру создают виртуальный COM порт. Преобразователь может подключаться к прибору посредством проводного (RS-485) или беспроводного (инфракрасный канал) соединения. Прибор всегда является ведущим, то есть информацию выдает только по запросу от компьютера (получил корректный запрос - выдал ответ). Целостность запросов и ответов определяется циклическим избыточным кодом в конце запроса или ответа. Текущая реализация На данный момент я создал класс для работы с прибором. Экземпляр этого класса будет создаваться и работать в отдельном потоке. В классе будут реализованы конкретные функции для работы с прибором (например - прочитать серийный номер прибора). Каждая из этих функций подготавливает соответствующий запрос прибору и вызывает внутреннюю функцию обмена данными SwapData. Указанная функция, по сути, выполняет основную работу класса: отправляет созданный запрос в COM порт и получает ответ из COM порта. Именно данную функцию я не могу написать. Начало функции SwapData выглядит примерно так:
Описание проблемы Прием ответа от прибора сопряжен с несколькими трудностями. Во первых, ответ необходимо принять максимально быстро. То есть, не должно быть простоев в работе функции SwapData. Во вторых, на один и тот же запрос прибор может ответить разным количеством байт (либо вообще не ответить). Это связано с тем, что прибор может получить некорректный запрос (например, ошибка при передаче). Тогда он, скорее всего, вообще не ответит. Так же в каком-то конкретном приборе может быть отключена какая-то функция и прибор на запрос, связанный с этой функцией, выдаст не ожидаемое количество байт, а другое, которое сигнализирует об ошибке. В связи со всем этим появилась попытка решения задачи приема данных. Попытка реализации чтения данных В нижеприведенном коде я реализовал алгоритм, когдаПривожу код, который отвечает за прием данных:
Помогите советом как реализовать прием данных максимально быстро и полно.
0
|
|||||||||||
| 16.11.2016, 14:03 | |
|
Ответы с готовыми решениями:
67
Работа с COM портом работа с COM портом Работа с COM-портом |
|
86 / 86 / 6
Регистрация: 14.01.2011
Сообщений: 265
|
||
| 17.11.2016, 13:19 | ||
|
Формат ответа для modbus(пример) - адрес:00 функция:02 кол-во байт данных:03 данные 01 02 03 контрольная сумма 05 06
1
|
||
|
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
|
||||
| 17.11.2016, 13:28 [ТС] | ||||
ReadFile надо указывать количество считываемых данных... Хотя можно указать количество ожидаемых данных. Подскажите, как настроить таймауты COM порта.Добавлено через 1 минуту
0
|
||||
|
Модератор
3409 / 2181 / 354
Регистрация: 13.01.2012
Сообщений: 8,464
|
||||
| 17.11.2016, 13:31 | ||||
|
0
|
||||
|
86 / 86 / 6
Регистрация: 14.01.2011
Сообщений: 265
|
||
| 17.11.2016, 13:36 | ||
|
1
|
||
|
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
|
|||
| 17.11.2016, 13:47 [ТС] | |||
|
Было уже выяснено, что ждать следующий байт надо не более 5 мс после приема последнего (для скорости 9600). Если в течении 5 мс байт не пришел, значит прибор больше ничего не пришлет. Как реализовать такое ожидание, а так же отправку и прием данных в рамках одной функции SwapData...
0
|
|||
|
Модератор
3409 / 2181 / 354
Регистрация: 13.01.2012
Сообщений: 8,464
|
||||||
| 17.11.2016, 15:04 | ||||||
Сообщение было отмечено d7d1cd как решение
Решение
d7d1cd, как было написано в той самой теме
...после такой настройки функция ReadFile вернется как только будет пауза дольше чем 5 мс
1
|
||||||
|
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
|
|
| 17.11.2016, 16:31 [ТС] | |
|
vxg, почитал про структуру COMMTIMEOUTS. Отличное решение, скажу Вам. По крайней мере в теории. Но есть вопрос. После отправки запроса прибор не сразу начинает присылать байты ответа, а через время от 5 мс до 150 мс. То есть функция
ReadFile должна ждать не менее 150 мс поступления хотя бы одного байта. Как мне настроить таймауты для этого?Мое решение следующее. При чтении я указываю функции ReadFile гарантированно большое значение данных, больше которого прибор никогда не пришлет, например 200. Члену структуры ReadTotalTimeoutMultiplier задаю значение 1. Таким образом функция ReadFile будет ждать поступления первого байта 1*200=200 мс. Однако если поступит байт, то далее функция будет ждать следующего символа только 5 мс как указано в ReadIntervalTimeout. Все верно?
0
|
|
|
Модератор
3409 / 2181 / 354
Регистрация: 13.01.2012
Сообщений: 8,464
|
|
| 17.11.2016, 16:50 | |
|
d7d1cd, я только ReadTotalTimeoutConstant пользовался для гарантированного ограничения по времени всего запроса, предлагаю вам попробовать без наворотов как показано (только с ReadIntervalTimeout) - почему то мне кажется что система интерпретирует это значение именно как интервал, а не как время ожидания у моря погоды - то есть возможно она дождется первого символа и только потом будет засекать интервал. пробовать надо
Добавлено через 10 минут ...если вдруг окажется что она выйдет через 5 мс после вызова (засчитает ожидание за интервал), то просто вызывать ее в цикле заданное предельное количество раз (например 150 / 5 = 30)
0
|
|
|
188 / 41 / 12
Регистрация: 22.02.2016
Сообщений: 149
|
||
| 17.11.2016, 20:01 | ||
|
Если решите на ивентах сделать, вот функции ResetEvent, SetEvent, WaitForSingleObject
1
|
||
|
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
|
|
| 17.11.2016, 20:51 [ТС] | |
|
vxg, докладываю об экспериментах с прибором. Прибор подключен через преобразователь интерфейсов RS485 - USB. Преобразователь при подключении к компьютеру через USB создает виртуальный COM порт.
Скорость 9600 бод Сначала настроил таймауты порта по Вашему совету из этого поста. Отправил запрос прибору, на который он должен был ответить пакетом размером 11 байт (количество данных для чтения в функции ReadFile указал 200). Функция ReadFile прочитала только 4 байта. Пробовал несколько раз: читается от 3-х до 5-ти байт, не больше. Далее начал экспериментировать и выяснил, что при установке ReadIntervalTimeout = 15 читается каждый раз разное количество байт (от 3 до 11). При установке ReadIntervalTimeout = 16 стабильно читается 11 байт, то есть именно то количество, что и передает прибор.Скорость 1200 бод Далее изменил скорость обмена с прибором на 1200 бод. И, как это ни удивительно, но история повторилась. При ReadIntervalTimeout = 15 читаются не все данные, при ReadIntervalTimeout = 16 стабильно читается всё. Скорость 300 бод На скорости 300 бод ситуация стала несколько иной. При ReadIntervalTimeout = 16 и даже при ReadIntervalTimeout = 200 данные читались не все. Только при ReadIntervalTimeout = 1600 данные читались стабильно все. Делаю выводы Скорее всего прибор присылает данные согласно протоколу обмена, однако преобразователь интерфейсов и его драйвер COM порта "хулиганят" и передают данные от прибора в COM порт не синхронно с прибором. Именно по этой причине при установке ReadIntervalTimeout = 5 и даже ReadIntervalTimeout = 15 функция ReadFile читает не все данные. Точнее, она читает все, что есть в буфере COM порта, просто преобразователь еще не успел передать в буфер все те данные, что получил от прибора. Вывод: надо устанавливать значение ReadIntervalTimeout во первых в зависимости от скорости обмена и протокола обмена, а во вторых с запасом. Другой преобразователь интерфейсов может по-другому "хулиганить" и еще не известно в какую сторону. Мой преобразователь, по видимому, имеет задержку примерно в 11 мс. Думаю, что запас для других преобразователей в 20 мс и плюс длительность ожидания по протоколу обмена будет достаточна.P. S. Настройка ReadTotalTimeoutConstant Так же был произведен эксперимент, когда в прибор заведомо отправляется некорректный запрос. Если значение ReadTotalTimeoutConstant = 0, то так как прибор вообще не отвечает, функция ReadFile глухо зависает. При установке ReadTotalTimeoutConstant = 3000 функция ReadFile, как и предполагалось, возвращала управление через 3 секунды. При этом число прочитанных байт было равно 0, что и логично.
0
|
|
|
86 / 86 / 6
Регистрация: 14.01.2011
Сообщений: 265
|
||
| 18.11.2016, 06:02 | ||
|
1
|
||
|
Модератор
3409 / 2181 / 354
Регистрация: 13.01.2012
Сообщений: 8,464
|
|
| 18.11.2016, 09:52 | |
|
d7d1cd, почему-то мне кажется что настройки порта должны восприниматься преобразователем и в данном случае проблема может быть в том что устройство реально так отвечает. истину поможет установить либо честный COM-порт либо если с ним все будет так же - осциллограф
0
|
|
|
45 / 44 / 1
Регистрация: 11.07.2012
Сообщений: 1,024
|
|
| 18.11.2016, 11:56 | |
|
Разрешите поинтересоваться, а почему вы считываете данные из сом порта побайтно? Можно же использовать буфер FIFO в регистрах UART СОМ порта, тогда данные будут считываться пачками байтов, в зависимости от того какая микросхема UART установлена на вашем железе, я правда разбираюсь с СОМ портом не под виндой, а под досом, но компьютерное железо одно и тоже и не зависит от того, какая именно на него установлена операционная система. Может быть при настройке передачи данных через СОМ не побайтно, а пачками через FIFO у вас будет меньше проблем для чтения данных?
0
|
|
|
Модератор
3409 / 2181 / 354
Регистрация: 13.01.2012
Сообщений: 8,464
|
|
| 18.11.2016, 12:00 | |
|
седьмой, я не думаю что здесь речь о чтении по байтам если только ТС не зашел в свойства порта и не начал там терзать галочками и ползунками настройки буфера FIFO о которых как я понял вы говорите
1
|
|
|
86 / 86 / 6
Регистрация: 14.01.2011
Сообщений: 265
|
|
| 18.11.2016, 12:13 | |
|
1
|
|
|
45 / 44 / 1
Регистрация: 11.07.2012
Сообщений: 1,024
|
|
| 18.11.2016, 18:53 | |
|
А нельзя разве посмотреть какие ошибки появляются во время чтения данных по СОМ порту, если вы говорите что настройки стандартные и данные передаются через FIFO буфер UART сом порта, то в современных компьютерах пачки данных должны передаваться сразу по 512 байт . И если данных в компьютер приходит меньше, чем поступило на входе, то в регистре LSR может быть код ошибки ( данные в компьютер считываются медленнее, чем поступают на входе и тогда часть данных затирается 1й бит регистра LSR; 2й бит этого регистра - ошибка паритета, 3й бит ошибка кадра, 4й- во время приема был обрыв линии и тд. ) Под виндой нет возможности проверки ошибок по регистру LSR (база+5) UART? Или в коде ошибки проверяются и их нет?
0
|
|
|
Модератор
3409 / 2181 / 354
Регистрация: 13.01.2012
Сообщений: 8,464
|
|
| 18.11.2016, 19:39 | |
|
седьмой, пропуска данных как я понял нет иначе система наверное бы вернула ошибку при чтении. В тех настройках UART что я видел максимум 16 байт (это не означает что будет читать по 16 байт - функция чтения возвращает и бОльшие блоки данных), не знаю о каких 512 идёт речь, наверное мы о разном
0
|
|
|
|
||
| 18.11.2016, 20:57 | ||
|
Есть готовые реализации:
1. Компонент BComPort 2. boost/asio Это легко ищется поиском по форуму. Я использую свой велосипед: https://www.cyberforum.ru/blog... g4416.html там можно посмотреть код.
1
|
||
|
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
|
||
| 18.11.2016, 22:09 [ТС] | ||
|
0
|
||
|
|
|||||||||||
| 18.11.2016, 22:24 | |||||||||||
|
Да и что мешает использовать OVERLOPPED режим что бы читать с таймаутами?
В духе:
Где: read нечто вроде:
Вырвал из реального кода отсюда Но полагаю 5мс число взятое от фонаря - уж слишком мало как мне кажется.
1
|
|||||||||||
| 18.11.2016, 22:24 | |
|
Помогаю со студенческими работами здесь
40
Работа с COM портом Работа с Com портом Работа с COM портом в Builder C++ 6.0 Работа с COM портом на С++ Builder 6 Работа с USB портом. Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
19. здоровье, усталость и психотип работника влияют на производительность предприятия, и наоборот, производительность на здоровье, усталось и психотип
anaschu 28.05.2026
Дискретно-событийная модель рабочего коллектива на AnyLogic: здоровье, выгорание, психотипы и микростимуляция
Привет, коллеги. Хочу поделиться итогами нескольких недель работы над симуляционной. . .
|
"Прокси" для последовательного порта
Eddy_Em 28.05.2026
Эту штуку написал я достаточно давно. Но сейчас вот понадобилось настроить датчик грозы, но при этом не отключать его от "метеодемона". Соответственно, надо запустить этот "прокси": метеодемон будет. . .
|
Рефакторинг программы уравнивания.
Massaraksh7 26.05.2026
Пример по предыдущей записи в блоге. Но, надо заметить, что, во-первых, там оптимизация не только математики, но и работы с базой данных, и с графами, а во-вторых, это ещё не всё.
|
Использование TThread в Lazarus для математических вычислений.
Massaraksh7 25.05.2026
Производя рефакторинг своих программ на предмет ускорения их работы, обратил внимание на такой аспект, как сокращение времени матвычислений. Дело в том, что приходится работать с большими матрицами. . .
|
|
Модель здравосохранения 18. Чем здоровее работник, тем быстрее выгорает
anaschu 24.05.2026
Имитационная модель корпоративного здравоохранения: что показывает математика
Сегодня в модели рабочего коллектива на AnyLogic появились три новые механики — выгорание через накопленную усталость,. . .
|
Модель здравосохранения 17. Планы на выгорание
anaschu 23.05.2026
Вот конкретная схема реализации:
В классе Работник добавить:
накопленнаяУсталость — растёт каждый час работы, снижается в перерывы и болезни
коэффициентПрезентеизма — снижает продуктивность. . .
|
Изменение цветов в палитре gif файла aka фавикона
russiannick 23.05.2026
Изменение цветов в палитре gif файла, юзаемого как фавиконка в составе html-файла, помещенная в base64, средствами нативного Java Script, навеянное сном в майский день.
Для работы необходим браузер,. . .
|
Модель здравосохранения 16. Слишком хорошие и здоровые сотрудники уходят, недовольные зарплатой
anaschu 23.05.2026
Отладка увольнений и настройка производительности
Сегодня во второй половине дня разобрались с механикой увольнений и настроили коэффициент сложности заданий. Вот что было сделано.
. . .
|