QT: проблемы с постоянным чтением данных из последовательного порта - PullRequest
1 голос
/ 06 августа 2020

Я читаю данные из последовательного порта с помощью QT, в главном окне я написал этот код:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QTextStream>
#include<QSerialPort>
#include<QSerialPortInfo>
#include<QtDebug>
#include<QThread>
QSerialPort *serial;
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent),
     ui(new Ui::MainWindow),
      m_standardOutput(stdout)
{
     ui->setupUi(this);
    serial= new QSerialPort(this);
    serial->setPortName("COM3");
    serial->setBaudRate(QSerialPort::Baud115200);
    serial->setDataBits(QSerialPort::Data8);
    serial->setParity(QSerialPort::NoParity);
    serial->setStopBits(QSerialPort::OneStop);
    serial->setFlowControl(QSerialPort::NoFlowControl);
    serial->open(QIODevice::ReadOnly);



    connect(serial, &QSerialPort::readyRead, this, &MainWindow::ReaderH);

    float HUM;
     HUM=H;

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::ReaderH()
{

        quint64 X=20;
    serial->waitForReadyRead();
    m_readData=serial->QSerialPort::read(X);
    //if (!m_timer.isActive())
      //     m_timer.start(5000);
     inter2=QString(m_readData);
    QStringList firstlist2= inter2.split(";");
    m_readData3=firstlist2.takeFirst();
    H=m_readData3.toFloat();
     qDebug() <<"Data:"<<m_readData<< " \r\n";
    //QThread::sleep(11);


}

программа правильно считывает данные в течение нескольких секунд, через некоторое время чтение начинает не совпадать по фазе, например:

Data: "60.904655; 25.779804 $"

Данные: «60.970406; 25.816269 $»

Данные: «60.988335; 25.798037 $»

Данные: «60.»

Данные: «883736; 25,7»

Данные: «61570 $»

Данные: «60.»

Данные: «91063»

Данные: «7; 25.779804 $»

Данные: «60.»

Данные: «934544; 25.»

Данные: «798037 $»

Данные: «60»

Данные: ".871784; 25.798037 $"

Не понимаю, как решить проблему. Спасибо за ваше время.

1 Ответ

0 голосов
/ 06 августа 2020

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

Класс декодера обычно имеет внутренний буфер и может выглядеть так:

class Decoder : public QObject
{
    Q_OBJECT

signals: 
    void messsageReceived(QByteArray message);

public:    
    void decode(const QByteArray& bytes)
    {
        for (char c : bytes)
        {
            if (c == '$')
            {
                emit messsageReceived(m_buffer);
                m_buffer.clear();
            }
            else
            {
                 m_buffer.append(c);
            }
        }
    }

private:
    QByteArray m_buffer;
};

Также обычно нет гарантии, что вы начнете чтение в начало пакета. Первое чтение может произойти в середине пакета, поэтому большинство протоколов используют последовательность «Старт» и «Стоп», или вам следует отбросить первый пакет, если вы не можете проверить его согласованность. В приведенном выше фрагменте первый пакет не обрабатывается.

Кроме того, последовательные порты не гарантируют передачу байтов без ошибок по линии, поэтому обязательно наличие механизма проверки, если данные разумны, например как контрольную сумму (т.е. CR C). Если некоторые данные повреждены, пакет следует отбросить, и, возможно, необходимо установить механизм на более высоком уровне, чтобы пакет был повторно передан (при необходимости).

...