Почему при передаче строки через UART-USB преобразователь на виртуальный COM порт, строка отображается частями?

Как можно обновить код приложения на PyQt5 для читаемости полных строк, отправляемых по UART-USB соединению, вместо их фрагментирования? Какие различия между методами `readLine()` и `readAll()` и как это может помочь решить проблему фрагментации строк? Требуется ли добавление символов `\r\n` при использовании метода `readLine()`?
  • 11 января 2024 г. 15:22
Ответы на вопрос 2
Возможная причина фрагментации строк при передаче их через UART-USB преобразователь на виртуальный COM порт и последующем их отображении в приложении на PyQt5 заключается в том, что данные по UART передаются пакетами, размер которых может быть ограничен буфером UART или USB. Соответственно, приложение может читать данные порциями так, как они поступают, что приводит к фрагментированному отображению.

Рассмотрим методы `readLine()` и `readAll()` и их использование в контексте приема данных через последовательный порт в PyQt5:

- `readLine()` - считывает данные из буфера до тех пор, пока не встретит символы перевода строки (`\n`) или возврата каретки (`\r`). Этот метод идеально подходит для считывания целых строк данных, если они отправляются с подобным разделителем. Если данные отправляются с завершающими символами `\r\n`, то `readLine()` прочитает всю строку до `\r\n` и остановится, что позволит избежать фрагментации.

- `readAll()` - считывает все доступные в буфере данные независимо от наличия в них каких-либо специальных символов. Использование этого метода может привести к чтению частичных строк, если данные были разделены при передаче, или если они приходят быстрее, чем успевают обрабатываться приложением.

Для обновления кода приложения на PyQt5 для обеспечения читаемости полных строк, можно поступить следующим образом:

1. Использовать `readLine()`, при этом убедиться, что отправляемые данные завершаются символами `\r\n`.

2. Аккумулировать данные в буфере до тех пор, пока не будет принят полный пакет, а затем обрабатывать их.

3. Устанавливать в системе приема данных временные маркеры (таймеры), чтобы ждать окончания приема всех частей сообщения перед обработкой.

Вот пример кода, который можно использовать для чтения полных строк при помощи `readLine()` в PyQt5:

```python
from PyQt5.QtCore import QIODevice
from PyQt5.QtSerialPort import QSerialPort, QSerialPortInfo

# ... (другой код для настройки QApplication, главного окна и т.д.)

def on_ready_read():
    while serial_port.canReadLine():
        line = serial_port.readLine().data().decode().rstrip('\r\n')
        # Обработка прочитанной строки
        print(line)

serial_port = QSerialPort()
serial_port.setPortName('COMx')  # Замените 'COMx' на имя нужного вам порта
serial_port.setBaudRate(QSerialPort.Baud115200)
serial_port.open(QIODevice.ReadWrite)
serial_port.readyRead.connect(on_ready_read)

# ... (другой код для запуска цикла обработки событий)
```

В этом коде, когда доступен новый набор данных для чтения, вызывается слот `on_ready_read()`, который считывает строки одну за другой при помощи метода `serial_port.readLine()` до тех пор, пока они доступны. Символы `\r\n` удаляются из принятой строки.

Таким образом, для избежания фрагментации данных важно корректно настроить процесс приема (с учетом времени задержки, максимальных размеров пакетов и правильных разделителей) и обеспечить соответствие
Они отображаются по мере приема данных и опроса буфера приема(аппаратного). 
Само собой опрос буфера приема не синхронизирован с отправкой данных.
Он опрашивается настолько часто что там только всегда куски передачи.
Принимайте в свой буфер, накапливайте и обрабатывайте по приему символа конца строки("\r\n").
Похожие вопросы