Перейти к содержанию
    

Асинхронный UART под виндой (задержка при приеме данных)

 

Товарищи,

Нужно из программы на виндовс передавать и принимать данные по UART для микроконтроллера.

При приеме возникает непонятная задержка в ~35 мс. 

По замыслу программа на ПК получает данные от микроконтроллера и сразу отправляет ему новые данные.

Явно в моей программе для ПК что-то не правильно. 

UART1.thumb.png.4ad3f27b397ef2170f3099fb6ed67528.png

В программе для винды задаю SetCommTimeouts. Судя по прочитанной документации ReadIntervalTimeout = 1 означает, что при возникновении паузы между принимаемыми байтами более 1мс считается, что прием закончен.

 CommTimeouts.ReadIntervalTimeout = 1;                // Если пауза после приема очередного байта превысит 1мс, то считается, что прием закончен
 CommTimeouts.ReadTotalTimeoutConstant = 0;
 CommTimeouts.ReadTotalTimeoutMultiplier = 0;
 SetCommTimeouts(hSerial, &CommTimeouts);

Далее создаю отдельный поток для асинхронного приема:

hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc, &dwParam, 0, &dwThreadId);     

Вот сама функция этого потока:

// Поток приема данных из UART
void WINAPI ThreadProc(PVOID* dummy)
{
  while (1)
  {
   ReadFileEx(hSerial, DataBuf, sizeof(DataBuf), &OverLap, (LPOVERLAPPED_COMPLETION_ROUTINE)RxComplete);// Запустить асинхронный прием из UART
   SleepEx(INFINITE, TRUE);                                                                             // Как только RxComplete отработает, SleepEx выйдет                                                                                                                                                
  }
}
 


Функция обработки принятых данных:

void WINAPI RxComplete(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
{
  if (dwNumberOfBytesTransfered != 0)
  {
   if (PacketAnalyze(DataBuf, dwNumberOfBytesTransfered) == 1)
   {
     ...
    WriteFileEx(hSerial, DataBuf3, Len, &OverLap2, (LPOVERLAPPED_COMPLETION_ROUTINE)TxComplete);  // посылаем транспортный пакет в UART
    SleepEx(INFINITE, TRUE);                                                                      // Дожидаемся пока отправит
   }
}

Подскажите, почему такая задержка между приемом и передачей возникает ?

Приоритет потока менял, почти не влияет на задержку.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

вы забудьте про времена, когда работаете с виндой. они не работают вообще. никакие. ни тайм ауты ничего.только как то на уровне порядка величины.  у вас очевидно стоит виртуальный com порт. это вы еще очень быстро все видите. и 35 у вас, скорее всего, очень усреднено. не знаю досконально деталей (может даже есть порты у которых передача в другом режиме),  здесь разбирали с точностью до размера буфера каждой микросхемы виртуального com  порта. то ,  что я для себя определил, как практическая рекомендация : обмен в сторону компьютера происходит кадрами. в экспериментах я вижу время порядка 50 миллисекунд. оно, скорее всего, реально 51 с чем то миллисекунда - историческая временная сетка одного их каналов таймера еще 86 машин  (18.2 раза в секунду). с этой временной сеткой в компьютер идут кадры ,  такой режим usb обмена. можно такую аналогию. считайте, что в комп идут автобусы. ваша посылка, попадающая на вход микросхемы виртуального порта, может попасть или в один автобус или в два или в три. если она попадает в один автобус ,  то поедет в комп в соответствии с расписанием или сразу или с промежуточной зедержкой до 50 миллисекунд. если посылка успела вся попасть в микросхему до отправления автобуса - она поедет вся на этом. если нет - часть уедет на этом ,  а часть через 50 миллисекунд на следующем. т е в непрерывном потоке в сторону компа вы получите 50 миллисекундный разрыв. с длинными и непрерывными посылками будете получать разрывы. возможна ли ситуация переполнения буфера микросхемы при непрерывной передаче? до определенной скорости нет. но я не прикидывал.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

дело не только во ftdi/ а и в 340 341 (не рекомендую). pl2303  (не рекомендую).  CP210x.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, firstvald said:

вы забудьте про времена, когда работаете с виндой. они не работают вообще. никакие. ни тайм ауты ничего.

Понятно. То-есть не решаемая задачка.

А как-же Agilent делали/делают осциллографы на Windows (XP) ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 26.04.2024 в 17:52, TOG сказал:

А как-же Agilent делали/делают осциллографы на Windows (XP) ?

У них, грубо говоря, свой синхронизатор, т.е. они накапливают данные в буфер синхронно, а потом передают винде с метками времени.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, TOG said:

А как-же Agilent делали/делают осциллографы на Windows (XP) ?

Там винда только GUI, картинки рисует, реалтаймом она не занимается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

это, кстати, накладывает серьезные проблемы на прием модбаса. работа приложения по стандарту практически невозможна. там приходится задирать тайм ауты, чтобы на дырки в приеме не реагировало приложение.

некоторой лазейкой может быть использование не виртуального com порта, а специального драйвера микросхемы моста . но, это - совсем отдельная история.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Почти на каждой материнской плате есть COM-порт. Выведите его "наружу" - многие проблемы отпадут...

UPD: Цена вопроса - всего-то 300 руб.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот что выяснил:

Задержка при приеме из виртуального COM-порта  возникает, если ReadFileEx не знает сколько байт нужно принять и ждет паузы между принятыми байтами.

Например так : ReadFileEx(hSerial, DataBuf, sizeof(DataBuf), &OverLap, (LPOVERLAPPED_COMPLETION_ROUTINE)RxComplete);

Примет он например 10 байт, паузы дождется(по факту плюс еще 35 мс) и вызовет RxComplete. 

Если же четко задать сколько байт надо принять (например 1 байт), то все происходит намного быстрее. Задержка между приемом и отправкой ~ 3 мс.

ReadFileEx(hSerial, DataBuf, 1, &OverLap, (LPOVERLAPPED_COMPLETION_ROUTINE)RxComplete);

Конечно теперь придется другой функции разбираться в этой каше, искать где начало данных, но в принципе задержка стала почти в 10 раз меньше.

UART2.thumb.png.e08afe1c002d881eb25833709c249773.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, TOG said:

Если же четко задать сколько байт надо принять (например 1 байт),

Ага, помеха спомеховала и один из байтов в посылке потерялся. Поэтому никуда вы от таймаутов не уйдёте, потому что никогда не знаете, сколько отправилось байт в линию, и сколько дошло до вашего приёмника..

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

18 minutes ago, tonyk_av said:

Ага, помеха спомеховала и один из байтов в посылке потерялся. Поэтому никуда вы от таймаутов не уйдёте, потому что никогда не знаете, сколько отправилось байт в линию, и сколько дошло до вашего приёмника..

Да, именно это и произошло сейчас. Половина данных передается нормально, потом какая-то помеха прилетает и все помирает. Тут нужно видимо делать интеллектуальную функцию по поиску данных в этой каше. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 hours ago, TOG said:

Тут нужно видимо делать интеллектуальную функцию по поиску данных в этой каше. 

Тут нужно брать интерфейс и протокол, подходящий под вашу задачу, а не пытаться натягивать сову на глобус.

Да, можно, пытаться разбирать принятые данные на предмет их похожести на посылку. Делал такое, но не от хорошей жизни. Выше дали дельный совет про накопление данных с метками времени. Это общий подход. В моё случае можно было обойтись без меток времени, что упростило обработку. В любом случае, с UART и под Выньдой ни о какой минимизации времени реакции при обмене по UART речи не идёт.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...