2017-06-05 87 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