我正在开发一个从600Hz传感器接收数据的Windows应用程序。在五分之二的情况下,我的IO线程成功地从传感器读取4个字节的数据并将其传递给GUI线程。
问题是五次中的三次,QSerialPort有无法解释的超时,其中QSerialPort的waitForReadyRead()返回false而serial.errorString()有超时错误。在这种情况下,它永远不会读取数据。如果我从串行端口读取,尽管超时错误,我将在下一个waitForReadyRead中读取2000+字节的数据,这将以块的形式提供,这会使我的应用程序的实时数据接收方面过时。
我尝试使用串口的readyRead()信号,但它表现出相同的行为,即。如果出现超时错误,则不会触发readyRead()信号。
更新:我能够使用Qt的终端示例([QT_INSTALL_EXAMPLES] / serialport / terminal)重现该问题,该示例使用非阻塞读取。错误的频率相当低,但它仍然存在。
更新:使用串行端口监视器,我可以看到当它卡住时,Qt终端示例卡在IOCTL_SERIAL_WAIT_ON_MASK上,我的示例在IOCT_SERIAL_WAIT_ON_MASK之后卡在IRP_MJ_WRITE DOWN上。这种情况从未发生在其他终端软件上,这让我认为问题肯定与Qt有关。
Pastebin of Serial Port Monitor Output
void IOThread::run(){
QSerialPort serial;
serial.setPortName(portname)
serial.setBaudRage(QSerialPort::Baud115200);
serial.setStopBits(QSerialPort::OneStop)
serial.setParity(QSerialPort::NoParity);
serial.setDataBits(QSerialPort::Data8);
serial.setFlowControl(QSerialPort::NoFlowControl);
if(!serial.open(QIODevice::ReadWrite)
{
qDebug() << "Error Opening Port";
return;
}
else
{
qDebug() << "Error Message: " << serial.errorString() // prints "Unknown Error"
}
while(true)
{
if(serial.waitForReadyRead(1000))
{
qDebug() << "Normal read";
reception_buffer = serial.readAll();
}
else
{
qDebug() << "Timeout";
/* serial.readAll() here will read nothing but force next read to read huge chunk of data */
continue;
}
}
// Process data...
}
答案 0 :(得分:0)
如果这有任何不同,请尝试:
while (true) {
QByteArray reception_buffer;
if (serial.waitForReadyRead(1000)) {
reception_buffer = serial.readAll();
while (serial.waitForReadyRead(10)) {
reception_buffer += serial.readAll();
}
qDebug() << "reception_buffer ready";
}
else {
qDebug() << "Timeout";
}
}
如果您想阻止来自waitForReadyRead
的超时,您可以设置:
if(serial.waitForReadyRead(-1))
bool QSerialPort::waitForReadyRead(int msecs = 30000)将在msecs毫秒后超时;默认超时为30000毫秒。如果msecs为-1,则该函数不会超时。
答案 1 :(得分:0)
卡在IOCTL_SERIAL_WAIT_ON_MASK
上
最可能的问题出在您的硬件或驱动程序中。 QSP使用基于WaitCommEvent的异步通知。如果WaitCommEvent卡住了 - 那么你的设备或驱动程序就会出现问题(最有可能)。
答案 2 :(得分:0)
感谢QSerialPort的工作人员,通过应用此补丁解决了Qt 5.10.1中的这个错误:https://codereview.qt-project.org/#/c/225277/
&#34;当数据到达设备时,QSP可能会忽略所有读取事件 开场。在这种情况下,即使重新打开设备也不会 救命。原因是之后启用了QWinOverlappedIoNotifier 比调用的startAsyncCommunication(),可能导致 忽略所有EV_RXCHAR事件。解决方法是启用 通知之前的通知程序,而不是任何称为I / O操作的通知程序。&#34; - Denis Shienkov,QSerialPort Maintainer