2017-06-05 88 views
0

我一直在挣扎着一个项目,它通过Qt中的串口进行通信大约两周。首先我尝试了信号/插槽方法,它错过了一些数据。然后我决定用这个线程,但是我得到了相同的结果。当应用程序窗口被调整大小或最大化/最小化时,即使在窗口栏上按住鼠标左键,它也会错过一些数据。请帮助我解决这个问题。带线程的QSerialPort

的主窗口构造函数:

SerialPort *serial= new SerialPort(); 
serial->moveToThread(&cThread); 

connect(this , &MainWindow::finished, &cThread, &QThread::quit); 
connect(this , &MainWindow::destroyed, this, &SerialPort::deleteLater); 
connect(serial, &SerialPort::getData, this, &MainWindow::displayData); 

cThread.start(); 

串口读取线程:

void SerialPort::newData() 
{ 
    mutex.lock(); 
    bArray.insert(bArray.length(),serial->readAll()); 
    mutex.unlock(); 

    emit getData(&bArray,&mutex); 
} 

一个串口构造:

serial = new QSerialPort(); 
connect(serial, &QSerialPort::readyRead, this, &SerialPort::newData); 

bArray.clear(); 

fill_serial_ports(); 
portName = find_stm32_port(); 

serial->setReadBufferSize(20*1024*1024); // it's a huge buffer. 
bArray.reserve(20*1024*1024); // it's a huge buffer. 

open_serial_port(); 

另外,我认为这可能是一个错误是什么错过了一些数据并写入了错误跟踪器。受让人说QSerialPort从来没有丢失数据,我的代码是错误的。我很困惑,我不知道在哪里犯错误。请,你能检查我的其他解决方案吗?错误在哪里?

我的bug跟踪报告(不接受):https://bugreports.qt.io/browse/QTBUG-61233

+2

请问一些示例代码? –

+1

偏离主题,但是......如果你的单线程代码缺少来自端口的数据,那么我不禁感觉到将该代码移动到另一个线程只会使*真实*问题更难调试。 –

+0

如果您要从串口接收大量数据,您可能需要累积从几个readyRead信号接收到的数据。 – Jeka

回答

0

尝试移动你的内心QSerialPort对象serial线程cThread太:

SerialPort *serial = new SerialPort(); 
serial->moveToThread(&cThread); 
serial->serial.moveToThread(&cThread); // move you inner QSerialPort to cThread 

在上面的代码内部的场serial->serial.moveToTheThread(...)确实神奇。

+0

我会试试这个,我也认为这可能是一个错误,并写入bug跟踪器。受让人说QSerialPort从来没有丢失数据,我的代码是错误的。我很困惑,我不知道在哪里犯错误。请,你能检查我的其他解决方案吗?错误在哪里?我只是将链接添加到我的主帖。 –

+0

您的代码存在以下问题: 1.为什么SerialPort从QThread继承?你在你的'SerialPort'类中混合了3个职责:(a)线程,(b)同步,(c)串口封装。这可能会导致不可预知的和真正奇怪的错误。使用聚合而不是继承。 2.什么原因从'SerialPort'继承'convertData'?这可能是一个真正的问题来源。改为使用“责任链”设计模式。 3.将'serial-> moveToThread(* this)'行添加到'SerialPort :: SerialPort()'。 4.重构你的代码,再试一次,然后回来。 – dekin

+0

我刚刚在示例中尝试了终端程序,并添加了几行代码以启动MCU。它也错过了数据。如果USB_Can转换器的红色指示灯亮起,则表示没有传输。然而,尽管Hercules是一个串口终端程序,但没有丢失数据。 你可以在下面的视频中看到它。 链接:https://drive.google.com/file/d/0B7WvtYBLRY0YVFFmRzZvWWZKVFk/view –

0

而被调整或最大化/最小化应用程序的窗口,甚至保持了窗口栏上的鼠标左键,它错过了一些数据

我编译the code you provided to a bug tracker,有一对虚拟串口的启动它端口与socat创建:

socat -d -d pty,raw,echo=0 pty,raw,echo=0 

和模拟发送数据块,用1个字节的每个第二增加它们的尺寸:

#!/bin/bash 
for i in {1..1000} 
do 
    dd if=/dev/urandom of=/dev/pts/25 bs=1 count=$i 
    sleep 1 
done 

你的应用程序的日志看起来像:

"bytearray length:1" 
"bytearray length:2" 
"bytearray length:3" 
"bytearray length:4" 
"bytearray length:5" 
"bytearray length:6" 
"bytearray length:7" 
... 

然后我试图调整应用程序窗口,移动,最大化/最小化,按下按钮等等。它没有任何作用:实际上,在相当长的测试期间,根本没有数据丢失(Ubuntu 16.04 x64)。因此,如果您仍然丢失数据,则可能是您的虚拟COM端口中存在问题,其描述为“STMicroelectronics Virtual COM Port”。

+0

感谢您的解释,但您的测试比我的应用程序慢,我的应用程序的波特率是1Mbit(由于CANbus)。 –

+0

好的,您认为数据丢失在哪里?这是否发生在你的convertData线程中? – dekin

+0

USBCan设备发出关于无法发送数据的错误,因此其错误导致正在变得越来越多。 –

0

,因为它是在the comment了澄清,问题是

的USBCAN设备提供有关无法发送的数据错误,因此其错误LED正在成为。

尝试添加以下行创建QSerialPort例如serial之后:

serial->setFlowControl(QSerialPort::HardwareControl); 

如果设备支持RFC232标准,这将使RTS(请求发送/ CTS(清除发送)线和原因你的发射机来请求发送任何数据之前接收的准备。详见here