我正在使用串行设备。 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在缓冲区中串行设备的数据完成之前被激活。知道如何解决这个问题吗?
答案 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置于不同的线程中绝对毫无意义。