QSerialPort-等待发件人的整个数据 [英] QSerialPort - wating for whole data from sender

查看:47
本文介绍了QSerialPort-等待发件人的整个数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用串行设备.QSerialPort在单独的线程中.线程是通过以下方式创建的:

I'm working with a serial device. The QSerialPort is in a separate thread. Thread is created this way:

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

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

When Data is available this signal in my thread worker is emited:

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

此功能可读取数据并检查数据是否正确-串行设备上的第二个字节表示剩余的数据包有多长时间...

This is the function that reads the data and checks if the data is correct - the second byte on my serial device says how long the rest of the packet is...

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已发出.知道如何解决这个问题吗?

My problem is that the signal QSerialPort::readyRead is emited before the data from the serial device is complete in the buffer. Any idea how to solve this problem?

推荐答案

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

There is absolutely NO guarantee that you'll get whole data at ONCE. You can solve this problem in some ways.

1)如果您有固定尺寸的包装,则可以执行以下操作:

1) If you have fixed size package you can do something like this:

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".此标头应至少包含开始"字节和数据大小(在您的情况下为第二个字节).标头应为固定大小.然后您可以执行以下操作:

2) If your package size may vary. Then you have to include "hader" in to your package. This header should contain at least "start" byte and data size (Its second byte in your case). And header shuld be fixed size. Then you can do something like this:

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放入不同的线程绝对没有意义.

And there is absolutely no point in putting your QSerial in to different thread.

这篇关于QSerialPort-等待发件人的整个数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆