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

时间:2016-07-03 11:32:29

标签: c++ qt serial-port qthread

我正在使用串行设备。 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 个答案:

答案 0 :(得分:3)

绝对 NO 保证您将获得ONCE的全部数据。您可以通过某种方式解决此问题。

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)如果您的包装尺寸可能有所不同。然后你必须在你的包裹中加入“黑客”。此标头应包含至少“开始”字节和数据大小(在您的情况下为其第二个字节)。标题是固定的大小。然后你可以做这样的事情:

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置于不同的线程中绝对毫无意义。