382 / 181 / 47
Регистрация: 11.07.2013
Сообщений: 993
|
||||||
1 | ||||||
Откуда при чтении из COM-порта берутся 99 байт?23.12.2014, 20:46. Показов 2270. Ответов 16
Метки нет Все метки)
(
Здравствуйте!
Этот отрывок кода взят из рабоче программы, которая работает около 2-х лет и судя по отзывам - успешно. Она написана на С++, я изменил только синтаксис, чтобы было понятно Дельфистам. Начало я опускаю - там ничего интересног (настройка DCB, установка тайм-аутов, очистка буфера приёма). А вот в этом месте и начинаются "чудеса": Например, мне надо принять 100 байт. Я устанавливаю nBufPRM равным 100, передаю запрос и получаю свои 100 байт. Код, приведённый ниже, работает таким образом: Функция WaitCommEvent() устанавливает ожидаемое событие - приём символа. Функция WaitForSingleObject() переводит объект в несигнальное состояние, из которого переход в сигнальное состояние произойдёт сразу же при получении первого байта данных. Далее, если всё нормально, функция ClearCommError() возвращает количество принятых байт и это кол-во будет прочитано, т.е мою исходную установку nBufPRM:=100 заменяет на nBufPRM:= comstat.cbInQue.
Вот исходник: Kod_C++.rar У меня только единственное объяснение - может не корректно происходит переход в сигнальное состояние и за это время успевают проскочить оставшиеся 99 байт... У кого и какое ещё есть мнение по этому поводу?
0
|
|
23.12.2014, 20:46 | |
Ответы с готовыми решениями:
16
Чтение из COM порта, При чтении из порта зависает read()
Откуда берутся лишние символы при создании массива с помощью оператора new? |
Пишу на Delphi...иногда
|
|
23.12.2014, 21:37 | 2 |
или по прошествии 125 мс после установки несигнального, но дальнейшая обработка произойдет, если перешло в сигнальное состояние - сработало требуемое событие (WaitForSingleObject == WAIT_OBJECT_0), далее ожидание асинхронной процедуры, которое не закончится, пока не будет получен результат (GetOverlappedResult с bWait == true), причем значение переменной A (_Out_ LPDWORD lpNumberOfBytesTransferred) тут, скорее всего, и будет равно 100 байтам, а далее comstat.cbInQue также должен быть равен 100 и т.д. (стоит проверить, но версия такая), если все именно так - как вариант отказаться от асинхронной работы с портом и перейти на синхронную
0
|
пофигист широкого профиля
4658 / 3093 / 854
Регистрация: 15.07.2013
Сообщений: 17,842
|
||||||
24.12.2014, 02:44 | 3 | |||||
А можешь объяснить вот эти строчки "чтобы они были понятны Дельфистам" (ну т.е. существам более низкого уровня).
С форума Си-шников тебя выгнали поганой метлой? ![]()
0
|
382 / 181 / 47
Регистрация: 11.07.2013
Сообщений: 993
|
|
24.12.2014, 09:27 [ТС] | 4 |
Согласен, но приём первого байта - это тоже результат. Следовательно после приёма первого байта успешно отработает ClearCommError() и перестроит функцию чтения ReadFile() на приём только одного байта nBufPRM:= comstat.cbInQue. В этом и заключается весь парадокс.
Не могу, т.к. изначально задано nBufPRM:=100, а здесь происходит подмена nBufPRM:= comstat.cbInQue;. ...извиняюсь, если Вас это обидело... Где-то слышал, что повышенная обидчивость, агрессивность - признаки психического растройства. Вам бы лечиться...
0
|
Пишу на Delphi...иногда
|
|
24.12.2014, 14:04 | 5 |
не забывайте про GetOverlappedResult, которая не завершится (bWait == true), пока не поступит вся посылка, а затем уже обрабатывается ClearCommError и т.д.
пошлите 1 байт - примите 1 байт, пошлёте 100 байт - примете 100 байт дабы дальше не гадать на кофейной гуще - посмотрите, какое значение у comstat.cbInQue в момент приема if nBufPRM then - в Delphi не пройдет, будет синтаксическая ошибка: или явное приведение типов (if BOOL(nBufPRM) then) или логическое выражение (if (nBufPRM > 0) then)
1
|
382 / 181 / 47
Регистрация: 11.07.2013
Сообщений: 993
|
|
24.12.2014, 16:40 [ТС] | 6 |
Спасибо за ответ, но это место что-то до меня не доходит: как она определяет что закончилось сообщение или нет, ведь она "не знает" ни о начальной установке nBufPRM, ни о установках COMMTIMEOUTS. А вдруг был передан только один байт, а дальше идут помехи (например симплексная связь), так получается что переход в сигнальное состояние произойдёт только по тайм-ауту и в буфере приёма будет куча мусора.
Стали бы Вы использовать такую конструкцию? Может лучше nBufPRM:= comstat.cbInQue; вообще выкинуть, пусть ReadFile() отрабатывает по изначально заданным nBufPRM и COMMTIMEOUTS
0
|
Пишу на Delphi...иногда
|
|
24.12.2014, 17:19 | 7 |
это определяется на физическом уровне (протокол RS-232), функции действуют на канальном уровне - м.б. с моделью могу ошибаться (с названиями уровней)
грубо говоря - определением того, что пришло - помехи или информационные значения определяется протоколом на одном уровне, программный интерфейс - другой (более высокий уровень) и он работает уже с данными, не "отвлекаясь" на организацию связи между устройствами и определения что пришло: данные, помехи или служебные сигналы можно и выкинуть, но как иначе узнать количество байт, имеющихся в приемном буфере в конкретный момент времени?
0
|
382 / 181 / 47
Регистрация: 11.07.2013
Сообщений: 993
|
|
24.12.2014, 20:55 [ТС] | 8 |
Вопрос снимается.
На канальном уровне контроллер порта осуществляет стробирование с частотой, превышающей скорость передачи, затем осуществляет статистическую обработку, на основании чего принимается решение о получении 0 или 1. Далее после получения стопового сигнала объект в течении какого-то небольшого промежутка времени удерживаетс в несигнальном состоянии, т.е. происходит ожидание очередного старта. Если получен старт, то цикл повторяется. Если старта нет, то объект переходит в сигнальное состояние. К сожалению величину этой задержки найти в литературе не смог. Мораль: если неизвестен момент, когда придёт пакет с данными, и его размер, то необходимо использовать именно этот алгоритм. Единственное, заранее нет смысла задавать размер ожидаемых данных nBufPRM. Добавлено через 3 минуты И ещё, если в пакете будут разрывы (это бывает при использовании сотовой связи), то затем на программном уровне придётся осуществлять сборку, т.к. вместо одного большого пакета может быть получено несколько маленьких.
0
|
пофигист широкого профиля
4658 / 3093 / 854
Регистрация: 15.07.2013
Сообщений: 17,842
|
|
25.12.2014, 03:10 | 9 |
Ну вот и сам понял, что я просил объяснить. Ну хотя бы суть того. То что тот код написан непонятно на каком языке - это уже прошлое.
А вот это уже ноу хау. И почему я всю свою уже весьма немалую жизнь в работе с последовательными портами разного рода был уверен, что "один большой пакет" не приходит никогда, никому, ни за какие деньги? И без "сборки" никакая программа работать нормально просто не сможет.
0
|
382 / 181 / 47
Регистрация: 11.07.2013
Сообщений: 993
|
|
25.12.2014, 22:56 [ТС] | 10 |
Уважаемый northener, я полагаю, что Вы человек далеко не глупый. Несмотря на то, что данный вопрос снимается с форума
мне всё-таки было бы интересно продолжить с Вами разговор на эту тему. Вы пишете, что
, т.е. Вы считаете себя профессионалом в вопросе работы с портами. В таком случае, как профессионал, поделитесь своим опытом. Вы могли бы привести отрывки из своих работ и комментарии к ним. Проще всего, конечно, критиковать других, быть такой "жирной жабой",сидящей на ветке и квакать. Ой, не обижайтесь, жаб я тоже люблю и не в коем случае не хочу задеть Ваше самолюбие - вдруг Вы опчять это воспримитеа на свой счёт, что жаб я считаю более низким сословием (а то меня и с форума Delphi прогонят сраной метлой, как Вы пишете).
Так что, принимаете вызов? А в качестве, так сказать, жеста "доброй воли" прикрепляю к сообщению замечательную (на мой взгляд) статью неизвестного, к большому сожалению, мне автора: COM-порт и TThread.rar Далее, разумеется, если Вы ответите конструктивно, буду выкладывать свои наработки в этой области (где-то лет так 30 тоже приходится соприкосаться с этим вопросом).
0
|
382 / 181 / 47
Регистрация: 11.07.2013
Сообщений: 993
|
|
25.12.2014, 23:32 [ТС] | 11 |
Ребята, хоть убейте, но пытался сегдня найти это:
Дизассемблировал всё, что смог, в т.ч. и kernek.dll, но так и не нашол подтверждения...
Добавлено через 12 минут Извиняюсь, отправил сообщение, но не проверил граматику. Следует читать не "kernek.dll" а "kernel.dll"
0
|
пофигист широкого профиля
4658 / 3093 / 854
Регистрация: 15.07.2013
Сообщений: 17,842
|
|
26.12.2014, 03:16 | 12 |
Считаю.
Могу.Проблема только с комментариями. Комментарии обычно пишутся для того чтобы можно было впоследствие понять очём шла речь. С учётом, что эти комментарии возможно будет читать другой человек, который будет продолжать твою работу. Но при этом имеется в виду, что этот другой человек имеет достаточные базовые знания. P.S. Насчёт "Ой, не обижайтес" можешь не страдать. Принимаю. Скачал сий опус.
0
|
382 / 181 / 47
Регистрация: 11.07.2013
Сообщений: 993
|
||||||
05.01.2015, 23:56 [ТС] | 13 | |||||
Вы считаете себя профессионалом -
Во первых, хочу Вас поздравит с 2015 годом и пожелать всего самого, самого, самого...!
Второе, как Вы заметили, я - С-ишнк (это я скрывал),однако к большому сожалению, до сих пор нет более менее нормального языка (если не считать Ассемблер) для работы с микроконтроллерами (кроме С), а это - моя и работа, и хобби, и (не хочу преувеличивать) смысл жизни! Не стану Вам рассказывать на форуме о своих личных успехах и проблемах (если Вам интересно, пишите на shyub@mail.ru, буду рад). Третье, вопрос или, пожалуй, решение. Проверил работоспособность кода в Lazarus 1.3 FPC 2.7.1. Выкладывю: COM_Port.rar Если бы не добавил вот это:
И последнее, дорогой апонент northener, хотел бы Вам привести в пример слова моего Учителя: "Не бойтесь спорить, если считаете себя правым. Истина - состязание личностей, состязание ваших знаний. Нет проигравших в вашем споре. Победа всегда за наукой!" (д.т.н. О.Г.Цебиногин - уже его нет)
0
|
382 / 181 / 47
Регистрация: 11.07.2013
Сообщений: 993
|
|
06.01.2015, 00:40 [ТС] | 14 |
К стати, чтобы не сложилось мнение у всех форумчан, что здесь два "длб...", живущих в районе МКАД о чём-то спорят, то признаюсь, что живу в г. Ташкенте (Республика Узбекистан).
0
|
пофигист широкого профиля
4658 / 3093 / 854
Регистрация: 15.07.2013
Сообщений: 17,842
|
|
06.01.2015, 05:07 | 15 |
Спасибо. И тебе того же.
И моя тоже. И тоже долгое время. "апонентом" меня ещё никогда , никто не обзывал. Даже не знаю гордиться или гневаться? P.S. Ну а где сам вызов? Ну т.е. вызов меня на дуэль? В том архиве, что ты привел куча мусора. Как ты эту кучу мусора используешь мне совсем не интересно. (Как я уже не раз сказал, геморрой есть у всех свой). Но работа с СОМ-портом всегда одна и та же. Ну пока не придумали и не внедрили что-то иное. Хотя вряд ли это кому под силу. Добавлено через 16 минут Грубо говоря могу, но не "забесплатно". Но и в этом случае я не обещаю, что возьмусь за решение твоей задачи.
0
|
382 / 181 / 47
Регистрация: 11.07.2013
Сообщений: 993
|
|
06.01.2015, 11:29 [ТС] | 16 |
Уклоняетесь. Иного и не ожидал.
0
|
пофигист широкого профиля
4658 / 3093 / 854
Регистрация: 15.07.2013
Сообщений: 17,842
|
|
07.01.2015, 01:43 | 17 |
Я на подобных "форумах" уже четверть века приблизительно. И на разводы типа "А слабо..." не реагирую.
![]()
0
|
07.01.2015, 01:43 | |
Помогаю со студенческими работами здесь
17
Формат столбца при выгрузке в Excel - откуда-то берутся шесть лишних нулей Подвисает при чтении COM порта Зависает при чтении com порта «Зависает» при чтении com порта Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |