|
|
  |
Windows7: прием байтов через COM-порт без потерь, Кто-то имеет личный опыт? чем побороть потерю отдельных байтов? |
|
|
|
May 23 2017, 20:00
|
Местный
  
Группа: Участник
Сообщений: 319
Регистрация: 27-09-07
Пользователь №: 30 877

|
Цитата(Ruslan1 @ May 23 2017, 20:13)  дада, спасибо, буду думать. А как без Synchronize это сделать? неужто через глобальные переменные нельзя? Просто скажите в каком направлении копать, я копать умею только где не знаю.... (Upd: извиняюсь, уже прочитал совет про евенты и семафоры, значит через них буду. Тогда уже сразу про очереди поищу, чтоб просто мессадж с новым указателем записи передать в ожидающую нитку- надеюсь оно тут есть где-то). Можно конечно и глобальные. а передавать сигнал гтовности другой нитке никоим образом не через Synchronize, а нормальными примитивами синхронизации потоков. классический вариант - семафор (у венды есть более облегченная версия - Event, но это малость несоотвествует задаче). надо собрать из вашего кольцевого буфера пакет, положить его в глобальную переменную, и отдать семафор сторонней принимающей нитке, или както просигналить что готово. както так. Цитата(Ruslan1 @ May 23 2017, 20:13)  У меня классический кольцевой буфер, в который один процесс что-то записывает по указателю записи, другой процесс -что-то читает по указателю чтения. Само собой, когда-то доходим до конца буфера и должны следующий байт в его начало записать. Я не понял Вашу идею про "никогда". Указатель записи доходит до RX_RINGBUFF_SIZE периодически, каждые RX_RINGBUFF_SIZE байт. С RX_RINGBUFF_SIZE - у вас все правильно, но переполнение кольцевого буфера вы действительно не контролируете. некрасиво это. я ушел от кольцевого буфера, ибо гемора с ним много - следить где голова где хвост. использую линейный буфер - в котором надо накопить целый пакет. как только пакет набрался - отдаю его, а остаток буфера перемащаю в начало. такая схема позволяет использовать чтение с заданием требуемой длинны, а не как у вас сейчас - ожидание любого события. событий летит много и часто, поэтому лучше использовать блокирующее чтение, и задать длину пакета. буфер в этом случае нужен чтобы проконтроливать качество полученного из порта, и откинуть ненужный мусор если он прилетит.
Сообщение отредактировал AlexRayne - May 23 2017, 20:06
|
|
|
|
|
May 24 2017, 12:53
|
Гуру
     
Группа: Свой
Сообщений: 2 360
Регистрация: 6-03-06
Из: Кишинев
Пользователь №: 15 025

|
Цитата(AlexandrY @ May 24 2017, 09:35)  Насколько вижу ни Intel 1037U ни его Platform Controller Hub (PCH) не имеют UART-ов. Значит ваши UART-ы виртуальные через USB. Я бы посмотрел что у вас еще на USB висит (камера, Wi-Fi...) и поотключал бы их жестким сносом драйверов из системы. Спасибо, интересная идея, не подумал про такое. Сериальные порты в BIOS Setup уже видны, или по этому признаку не определить через что оно работает? Есть какие-то низкоуровневые тестеры, чтоб подергали железо и сказали через какой чип оно работает и что еще на каком хабе сидит (если это USB)? Машинка используется вот такая. (кстати, эта модель очень понравилась по качеству исполнения) Но вряд ли дело только в этом, даже если так. Пробовал и с совершенно другим железом -то же самое видел. Думаю, глюки у меня в программе, займусь корректировкой и тестами ближе к выходным, материала и идей тут накидали достаточно, лишь бы время найти
|
|
|
|
|
May 24 2017, 12:55
|
Местный
  
Группа: Участник
Сообщений: 319
Регистрация: 27-09-07
Пользователь №: 30 877

|
Цитата(Ruslan1 @ May 24 2017, 16:53)  Спаисибо, интересная идея, не подумал про такое. Сериальные порты в BIOS Setup уже видны, или по этому признаку не определить через что оно работает? Есть какие-то низкоуровневые тестеры, чтоб подергали железо и сказали через какой чип оно работает и что еще на каком хабе сидит (если это USB)? Машинка используется вот такая. (кстати, эта модель очень понравилась по качеству исполнения) Но вряд ли дело только в этом, даже если так. Пробовал и с совершенно другим железом -то же самое видел. Думаю, глюки у меня в программе, займусь корректировкой и тестами ближе к выходным, материала и идей тут накидали достаточно, лишь бы время найти  А в диспетчере устройств это хозяйство не разглядеть?
|
|
|
|
|
May 25 2017, 22:14
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(sonycman @ May 22 2017, 15:48)  Тоже думаю, что проблема просто в переполнении ФИФО аппаратного приёмника. Потому, что винда тупо не успевает выгребать данные. Не думайте ибо этого не может быть. Даже если-б загрузка CPU была == 100%, драйвер COM-порта, работающий на высоком уровне привилегий, всё равно успевал бы всё выгребать. Тем более на такой низкой скорости. Тем более, что и загрузка CPU никакая. Цитата(AHTOXA @ May 24 2017, 09:07)  Я делал так: в потоке приёма создавал на куче пакет, собирал его, проверял валидность, потом отправлял главному окну указатель на этот пакет при помощи PustMessage(). Главный поток обрабатывал пакет и удалял его. Хмм... А очередь сообщений, связанная с окном и её обработка тредом окна гарантирует, что сообщения из этой очереди будут обрабатываться в том же порядке, в котором они постились в очередь? Тем более если постинг идёт из разных тредов? Я бы на это не рассчитывал. Да и вроде в случае межпоточной передачи сообщений, PostMessage аналогичен SendMessage-у. Цитата(DS @ May 22 2017, 21:49)  В 7 похоже, есть баг в COM драйвере. Многие программы, нормально работавшие с XP, глючат с ком-портами на 7. Единственное, что надежно под ней работает -USB-COM адаптер, причем с FTDI чипом. Моя программа, написанная много лет назад под WinXP, сейчас работает одновременно с 3-я компортами на Win8, каждый - на скорости 921600 бод (отладочные потоки 3-х устройств). Сейчас это COM-порты - на PCI-карте, раньше были - на USB-UART-ах (FTDI и CP210x), а также - комбинации того и другого. До этого всё так же работало на Win10 на другом компе. Работает это целыми днями. Так что проблема 99.9% не в виндовых дровах. А как всегда - в кривых руках написателей этих "многих программ". Проблемы возникают только с PL230x на высоких скоростях. На всех опробованных виндах. Вот тут явно дело в дровах Prolific.
|
|
|
|
|
May 25 2017, 22:37
|

Профессионал
    
Группа: Свой
Сообщений: 1 818
Регистрация: 15-10-09
Из: Владивосток
Пользователь №: 52 955

|
Цитата(XVR @ May 25 2017, 21:14)  WaitForSingleObject вызывать можно. Если WaitCommEvent не ушла в wait, то event останется в том состоянии, в котором был. А был он в установленом состоянии. А вот GetOverlappedResult неизвестно - MSDN на этот счет молчит У меня все работает нормально с WaitCommEvent и без WaitForSingleObject. Два подряд ожидания не есть хорошо: тут может быть потенциальная причина пропуска информации. После того, как WaitCommEvent дождалась события, я просто делаю ResetEvent, проверяю код события, по EV_RXFLAG делаю обработку, по другим либо возвращаюсь к WaitCommEvent, либо закрываю порт (если в основном потоке устанавливаю специальный флаг, сигнализирующий о необходимости закрытия)
|
|
|
|
|
May 26 2017, 07:05
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(jcxz @ May 26 2017, 03:14)  Хмм... А очередь сообщений, связанная с окном и её обработка тредом окна гарантирует, что сообщения из этой очереди будут обрабатываться в том же порядке, в котором они постились в очередь? Да, гарантирует: Цитата With the exception of the WM_PAINT message, the WM_TIMER message, and the WM_QUIT message, the system always posts messages at the end of a message queue. This ensures that a window receives its input messages in the proper first in, first out (FIFO) sequence. Цитата(jcxz @ May 26 2017, 03:14)  Тем более если постинг идёт из разных тредов? Без разницы. Цитата(jcxz @ May 26 2017, 03:14)  Я бы на это не рассчитывал. А здесь не надо гадать, надо просто читать документацию. Цитата(jcxz @ May 26 2017, 03:14)  Да и вроде в случае межпоточной передачи сообщений, PostMessage аналогичен SendMessage-у. Нет. ЗЫ. Совершенно очевидно, что вы не разбираетесь в теме ©.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
May 26 2017, 10:14
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(AHTOXA @ May 26 2017, 09:05)  Да, гарантирует: А здесь не надо гадать, надо просто читать документацию. Читать лень - сейчас это не нужно. Но помнится, что в WinAPI есть функции, позволяющие считывать сообщения из очереди по маске. А значит - в произвольном порядке. Цитата(AHTOXA @ May 26 2017, 09:05)  Нет. ЗЫ. Совершенно очевидно, что вы не разбираетесь в теме ©. Да ладно! А если внимательнее прочитать описание WinAPI?  Цитата(AHTOXA @ May 24 2017, 09:07)  Я делал так: в потоке приёма создавал на куче пакет, собирал его, проверял валидность, потом отправлял главному окну указатель на этот пакет при помощи PustMessage(). А если надо отправить сообщение не главному окну? Или у Вас всегда приложения только с одним окном?
|
|
|
|
|
May 26 2017, 10:33
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(rudy_b @ May 26 2017, 12:19)  Вероятность лишнего сброса события есть всегда. Нужна атомарная команда сброса события при условии отсутствия принятых байт, но ее нет и все зависит от реализации ОС. Проблем нет никаких при грамотном построении алгоритма: Принимающий тред пишет байты в кольцевой буфер. После каждого обновления содержимого буфера (или не после каждого, а при достижении некоего уровня + по таймауту) посылает нотификацию (оконным сообщением) треду, в котором находится управляющее окно. Управляющее окно, получив нотификацию, читает кольцевой буфер из приёмного треда. Естественно - парсинг потока байт на пакеты и уж тем более - обработку пакетов, желательно делать уже в треде управляющего окна. Не надо смешивать уровни обработки протокола. PS: И желательно, без реальной необходимости, избегать передачи указателей на блоки данных в куче между тредами. Как тут советуют некоторые товарищи....
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|