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

标签 c++ qt serial-port qthread

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

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

当数据可用时,我的线程 worker 中的这个信号被发出:

    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 应至少包含“开始”字节和数据大小(在您的情况下为第二个字节)。并且标题应该是固定大小的。然后你可以这样做:

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 放入不同的线程。

关于c++ - QSerialPort - 等待来自发件人的全部数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38169513/

相关文章:

C++ 组件系统问题

C++ 存储大量 map 坐标的最佳文件格式

c++ - 返回从 native C++ 调用编码的 System::String 时崩溃

c++ - QChar 如果 `isDigit()` 则获取数字值

c++ - 安全 bool 成语 bool_type(和安全 bool 成语)如何工作?

c++ - Qt 信号发射的段错误

c++ - 无法在 QThread 与多个 Qthread 的 finished() 信号之间进行连接

python - 使用 python twisted 框架连接到多个串行套接字

c++ - QtSerialPort 示例失败

windows - 串口数据损坏的异常模式