Как читать serial port qt
Перейти к содержимому

Как читать serial port qt

Чтение последовательного порта QT

Теперь я хочу прочитать данные через программу Qt5.3.

Итак, моя программа не захватывает данные . Мои вопросы:

  • Я что-то пропустил в настройке QSerialPort?
  • Если нет, почему нет отображения данных через qDebug ()

РЕДАКТИРОВАТЬ

Благодаря Майку я наконец могу прочитать это устройство USB . вот мой последний код

Большинство функций ввода-вывода в Qt асинхронны. Это означает, что readAll() не нужно ждать прибытия данных. Вместо этого он возвращает доступные на данный момент данные (данные, которые могут быть прочитаны с устройства без ожидания). В настоящее время вы просто вызываете readAll бесконечный цикл (это заставляет поток проводить все свое время в этом цикле и не может получить новые данные, которые, возможно, прибыли . )

Звонить нужно readAll только тогда, когда вы знаете, что поступили новые данные. Этого можно добиться двумя способами:

Неблокирующий асинхронный способ:

Используйте readyRead() сигнал, чтобы получать уведомления, когда в устройстве доступны новые данные, вместо бесконечного цикла. Вот как вы должны делать большинство вещей в Qt, чтобы иметь возможность действовать в соответствии с несколькими событиями, которые могут произойти в любое время. Ваш код можно переписать так:

Блокирующий синхронный способ:

Используется waitForReadyRead() для блокировки потока до тех пор, пока новые данные не поступят в последовательный порт. Это делает вызывающий поток неспособным делать что-либо, пока новые данные не поступят на этот последовательный порт. Если этот поток был потоком графического интерфейса, это приведет к тому, что приложение не будет отвечать в течение этого периода времени. Используйте этот подход только в том случае, если вы уверены, что именно этого хотите. Ваш код можно переписать так:

Использование библиотек QSerialDevice и Qwt для организации коммуникации с контроллером и отображения данных

В продолжение своей статьи «Простой электронный самописец» хочу поделится опытом создания терминала для сообщения с разработанным мной девайсом на основе библиотек QSerialDevice и Qwt, ну и естественно Qt. QSerialDevice работает с любым COM-портом (реальным или виртуальным) определенным операционной системой, поэтому не имеет значения каким способом контроллер подключен к ПК: непосредственно через адаптер UART->RS-232(MAX-232), через адаптеры UART->USB(FT-232, CP2101) или UART->Bluetooth(BTM-222), также можно, например, подключить Arduino-совместимое устройство (адаптер UART->USB уже напаян на плату). Qwt же — мощное средство отображения данных. Их общий плюс — кроссплатформенность, это же Qt, достаточно скомпилировать коды под нужной платформой — и все работает! Так что, кому интересно, прошу под кат!

Введение
  • считывание данных с com-порта по их поступлению (данные с 4х канального модуля АЦП на базе контроллера AVR)
  • обработка и вывод в виде графиков в реальном времени
  • запись обработанных данных в файл(ы)
  • безболезненная переносимость с одной платформы на другую

Специально для этой статьи, в целях лучшей иллюстрации возможностей библиотек (в особенности QSerialDevice), я написал упрощенный вариант своего терминала. На его примере я попытаюсь рассказать об основных моментах разработки, только лишь поясняя исходные коды тестового приложения.

Начнем

QSerialDevice берем здесь. Далее для подключения к проекту необходимо в файле проекта указать пути к файлам (предпочитаю unixstyle написания путей):

Qwt ищите тут. Кстати, общие сведения о QWT можно найти вот в этом хабрапосте, там в том числе описан процесс сборки, в связи с этим повторяться не буду. Подключаем библиотеку следующим образом: в командной строке:

в файле проекта:

SerialDeviceEnumerator

Библиотека QSerialDevice предоставляет интересную возможность — с помощью методов встроенного класса SerialDeviceEnumerator можно определить все присутствующие в системе последовательные порты, а также выудить информацию о каждом из подключенных устройств. Подробное описание класса присутствует в исходных кодах библиотеки, пример enumerator в папке с исходниками библиотеки хорошо иллюстрирует возможности его применения.

где procEnumerate (QStringList) заполняет списком доступных com-портов экземпляр класса QComboBox расположенный на главной панели:

Для того чтобы использовать все возможности класса SerialDeviceEnumerator нужно передать методу setDeviceName() имя интересующего порта в виде строки, присоединим к сигналу hasChanged(QStringList) еще один слот:

теперь в отладочную консоль выводятся сведения обо всех подключенных устройствах.

AbstractSerial

В то время как класс SerialDeviceEnumerator используется для обнаружения последовательных портов в системе и играет вспомогательную роль, основную функциональность библиотеки QSerialDevice несет класс Аbstract Serial.

В функции initSerial() создается экземпляр класса AbstractSerial, привязываются сигнал состояния signalStatus(QString,QDateTime) и сигнал readyRead() оповещающий о прибытии данных в com-порт к соответствующим слотам. При нажатии на кнопку Open на панели инструментов выполняется функция-слот procControlButtonClick() в которой объекту serial присваивается имя текущего порта в portBox открывается порт, дальше в отладочную консоль выводятся текущие параметры соединения, потом списки возможных значений параметров, а затем устанавливаются нужные параметры соединения.

С этого момента по появлению сигнала readyRead() управление передается функции-слоту procSerialDataReceive(), в которой собственно можно и организовать обработку данных. На данный момент функция выводит считываемые данные в текстовое окно вывода на базе элемента textEdit:

Функция-слот procSerialMessages(const QString &msg, QDateTime dt) выводит статусные сообщения по срабатыванию на сигнал signalStatus(QString,QDateTime):

Обработка и вывод данных. Кратко о Qwt.

Итак, как уже стало понятно, основное действо по обработке данных должно происходить в функции-слоте procSerialDataReceive(). Тут возможны варианты в зависимости от того, выводятся данные в реальном времени или же сначала сбор данных, потом — вывод. Если Вам достаточно второго, отсылаю к уже упомянутой статье. В рамках моей задачи необходимо снять сигналы с четырех каналов АЦП микроконтроллера и отобразить их изменения во времени на двух графиках в виде четырех кривых. Здесь рассмотрим простейший случай — одноканальный АЦП, соответственно: один график — одна кривая. Как известно в основе представления данных библиотекой Qwt лежит класс QwtPlot — само полотно графика, для отображения кривой используется класс QwtPlotCurve, для аккумуляции точек кривой — класс QwtArraySeriesData, для прорисовки кривой в реальном времени поточечно — класс QwtPlotDirectPainter, QwrSystemClock — для отсчета времени. Итак, в функции-слоте procSerialDataReceive() класса MainWindow формируем точку и добавляем ее к кривой и в файл при помощи методов appendPoint(QPointF point) и RecToFile(QPointF point), при этом предполагаем, что МК выдает данные в формате «Ch_номер_канала = число» в перемежку с тестовыми сообщениями.

Естественно, в зависимости от того в какой форме микроконтроллер выдает данные в com-порт зависит и содержимое фильтра данных в функции procSerialDataReceive(), смело подстраивайте его под собственные нужды.
Библиотека Qwt — очень мощный инструмент вывода данных, содержит в себе целый набор виджетов для создания интерфейсов типа QwtWheel, кроме того позволяет легко организовать печать, навигацию и зум графиков, так что внимательно смотрите документацию и используйте полностью весь функционал библиотеки.

QT Serial Port Reading

So there is no data catch by my program . My questions are :

  • Did i miss something in the setting of the QSerialPort ?
  • If no why there is no data display via the qDebug()

EDIT

Thanks to mike i can finaly read this usb device . here is my final code

1 Answer 1

Most IO functions in Qt are asynchronous. This means that readAll() does not wait for data to arrive. Instead, it returns currently available data (data that can be read from the device without waiting). Currently, You are just calling readAll in an endless loop (this makes the thread, spend all its time in this loop, unable to receive the new data that may have arrived. . .)

You need to call readAll only when you know that new data has arrived. This can be accomplished in two ways:

Non-blocking Asynchronous Way:

Use the readyRead() signal to get notified when new data is available in the device instead of looping forever. This is how you should do most stuff in Qt, In order to be able to act upon multiple events that may arrive at any time. Your code can be rewritten like this:

Blocking Synchronous Way:

Use waitForReadyRead() to block the thread until new data arrives to the serial port. This makes the calling thread unable to do anything until new data arrives on this serial port. If this thread was a GUI thread, This will make the application unresponsive during that period of time. Use this approach only when you are sure this is what you want. Your code can be rewritten like this:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *