我正在使用串行设备。 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/