QT:连续从串行端口读取数据的问题

时间:2020-08-06 08:31:45

标签: qt serial-port qtserialport

我正在使用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);


}

程序会正确读取数据几秒钟,一段时间后,读取开始异相,像这样:

数据:“ 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 :(得分:0)

从串行端口读取时,您需要自己将“流”切成“消息”。为了稳健起见,您不应对数据的时间做任何假设。

收到数据后,应将其输入“解码器”,即通常是一个类,该类读取每个字节的字节并找到数据包的“定界符”。

解码器类通常具有内部缓冲区,并且可能看起来像这样:

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;
};

通常,也不能保证您将在数据包的开头开始阅读。第一次读取可能发生在数据包的中间,这就是为什么大多数协议都使用“开始”和“停止”序列的原因,或者如果您无法验证其一致性,则应该丢弃第一个数据包。在上面的代码段中,第一个数据包未处理。

此外,串行端口不能保证在线路上无误传输字节,因此,如果数据敏感,则必须具有验证机制,例如校验和(即CRC)。如果某些数据损坏,则应丢弃该数据包,也许必须在更高级别上采用某种机制,以便重新传输该数据包(如果需要)。