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?
推荐答案
绝对不保证您将在 ONCE 获得全部数据.您可以通过某些方式解决此问题.
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.
相关文章