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

QT:从串行端口连续读取数据的问题,qt,serial-port,qtserialport,Qt,Serial Port,Qtserialport,我正在使用QT从串行端口读取数据,在主窗口中我编写了以下代码: #include "mainwindow.h" #include "ui_mainwindow.h" #include<QTextStream> #include<QSerialPort> #include<QSerialPortInfo> #include<QtDebug> #include<QThread> QSerialPort

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


}
#包括“mainwindow.h”
#包括“ui_main window.h”
#包括
#包括
#包括
#包括
#包括
QSerialPort*系列;
主窗口::主窗口(QWidget*父窗口)
:QMainWindow(父级),
ui(新ui::主窗口),
m_标准输出(标准输出)
{
用户界面->设置用户界面(此);
串行=新的QSerialPort(本);
串行->设置端口名(“COM3”);
串行->设置包速率(QSerialPort::Baud115200);
串行->设置数据位(QSerialPort::Data8);
串行->设置奇偶校验(QSerialPort::NoParity);
串行->设置停止位(QSerialPort::OneStop);
串行->设置流量控制(QSerialPort::NoFlowControl);
串行->打开(QIODevice::只读);
连接(串行,&QSerialPort::readyRead,this,&MainWindow::ReaderH);
浮沉的嗡嗡声;
HUM=H;
}
MainWindow::~MainWindow()
{
删除用户界面;
}
void主窗口::ReaderH()
{
64 X=20;
串行->waitForReadyRead();
m_readData=serial->QSerialPort::read(X);
//如果(!m_timer.isActive())
//m_定时器启动(5000);
inter2=QString(m_readData);
QStringList firstlist2=inter2.split(“;”);
m_readData3=firstlist2.takeFirst();
H=m_readData3.toFloat();

qDebug()从串行端口读取数据时,您需要自己将“流”切割成“消息”。为了保持健壮性,您不应该对数据的定时进行任何假设

当接收到数据时,您应该将其输入到“解码器”,即通常是一个按字节读取并查找数据包“分隔符”的类

解码器类通常有一个内部缓冲区,可能如下所示:

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)。如果某些数据损坏,则应丢弃数据包,并且可能必须在更高级别设置一个机制,以便重新传输数据包(如果需要)。

从串行端口读取数据时,您需要自己将“流”切割成“消息”。为了保持健壮性,您不应该对数据的定时进行任何假设

当接收到数据时,您应该将其输入到“解码器”,即通常是一个按字节读取并查找数据包“分隔符”的类

解码器类通常有一个内部缓冲区,可能如下所示:

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)。如果某些数据损坏,则应丢弃数据包,并且可能必须在更高级别设置一个机制,以便重新传输数据包(如有需要).

您似乎假设消息边界将被保留。事实并非如此。从串行端口连接到/从串行端口连接到的数据只不过是一个字节流——由您来解析传入数据并重新生成消息。您似乎假设消息边界将被保留。事实并非如此。要保存的数据/串行端口连接只不过是一个字节流——由您来解析传入的数据并重新生成消息。