QSerialPort - 等待来自发件人的全部数据

QSerialPort - wating for whole data from sender

我正在使用串行设备。 QSerialPort 在一个单独的线程中。 线程是这样创建的:

QThread* serialthread = new QThread;
Serial*  serial = new Serial();
serial->moveToThread(serialthread);

当数据可用时,我的线程工作者中会发出此信号:

    void Serial::process()
    {
        serialport = new QSerialPort();
        connect(this->serialport,SIGNAL(readyRead()),this,SLOT(readyToRead()));
    }
    void Serial::readyToRead()
    {
        emit SIG_dataAvailable(this->read());
    }

这是读取数据并检查数据是否正确的函数 - 我的串行设备上的第二个字节表示数据包的其余部分有多长...

QByteArray Serial::read() const
{
    QByteArray receivedData;
    int length;
    receivedData = serialport->readAll();
    length = receivedData[1];
    if(length != receivedData.length() - 1)
    {
        qDebug() << "protocol error.";
        return NULL;
    }
    return receivedData;
}

我的问题是信号 QSerialPort::readyRead 在来自串行设备的数据在缓冲区中完成之前发出。知道如何解决这个问题吗?

绝对没有保证您将一次性获得全部数据。您可以通过某些方式解决此问题。

1) 如果您有固定尺寸的包裹,您可以这样做:

void foo::onSerialRead()
{
    //! Is there whole datagram appears?
    if (m_serial->bytesAvailable() < ::package_size) {
        //! If not, waiting for other bytes
        return;
    }

    //! Read fixed size datagram.
    QByteArray package = m_serial->read(::package_size);
    //! And notify about it.
    emit packageReady(package);
}

2) 如果您的包裹尺寸可能会有所不同。然后你必须在你的包中包含 "hader" 。此 header 应至少包含 "start" 字节和数据大小(在您的情况下为第二个字节)。而 header 应该是固定大小。然后你可以这样做:

void foo::onSerialRead()
{
    static QByteArray package;
    static bool isHeaderRead = false;
    static quint8 startByte = 0;
    static quint8 dataSize = 0;

    //! Is there whole header appears?
    if (m_serial->bytesAvailable() < ::header_size) {
        //! If not, waiting for other bytes
        return;
    }

    if (!isHeaderRead) {
    //! Read fixed size header.
        package.append(m_serial->read(::header_size));
        QDataStream out(&package);

        out >> startByte;

    //! Check is it actually beginning of our package?
        if (Q_UNLIKELY(startByte != ::protocol_start_byte)) {
            return;
        }
        out >> dataSize;
        isHeaderRead = true;
    }

    //! Check is there whole package available?
    if (Q_LIKELY(dataSize > m_serial->bytesAvailable())) {
        //! If not, waiting for other bytes.
        return;
    }
    //! Read rest.
    package.append(m_serial->read(dataSize));
    //! And notify about it.
    emit packageReady(package);
    package.clear();
    isHeaderRead = false;
}

并且将您的 QSerial 放入不同的线程中绝对没有意义。