2013-12-15 24 views
1

我試圖通過USB串行電纜將微控制器與臺式PC連接。 我的臺式電腦的操作系統是Windows 8.1,USB串行電纜是TTL-232R-3V3。 (FTDI) (Qt版本:5.2.0 beta1,QtCreator版本:3.0,編譯器:MSVC2012)QSerialPort :: readLine在MS Windows上無法正常工作

現在我正在嘗試讀/寫環回測試,這就是爲什麼RX/TX引腳的USB串行電纜相互連接。

這是我的代碼。

#include <QtCore/QCoreApplication> 
#include <QtSerialPort/QSerialPort> 
#include <QtSerialPort/QSerialPortInfo> 
#include <QtCore/QDebug> 

#define PORT_NAME "COM3" 
#define BAUDRATE 19600 
#define TIMEOUT_MS 1000 

QT_USE_NAMESPACE 
int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 
    QSerialPort pSerial(PORT_NAME); 
    const char strMsg[] = "#1:Send data line \n #2:Send data line\n #3:Send data line end\n"; 
    char strBuf[256]; 
    qint64 nByte; 


    if(pSerial.open(QIODevice::ReadWrite)){ 
     pSerial.setBaudRate(BAUDRATE); 
     qDebug() << "OPEN PASS"; 

     pSerial.write(strMsg); 
     pSerial.flush(); 
     if(pSerial.waitForBytesWritten(TIMEOUT_MS)){ 
      qDebug() << "WRITE PASS"; 
     } 


     pSerial.waitForReadyRead(TIMEOUT_MS); 
     while(true){ 
      if(pSerial.canReadLine()){ 
       qDebug() << "CAN READ LINE"; 
       nByte = pSerial.readLine(strBuf,sizeof(strBuf)); 
       qDebug() << "Length: " << nByte; 
       qDebug() << "Read data: " << strBuf; 

      } 
     } 
     pSerial.close(); 
    } else { 
     qDebug() << "OPEN FAIL\n"; 
    } 
    return a.exec(); 
} 

當程序開始運行時,結果與我預期的不同。 只能接收到第一行發送的數據。因此,在控制檯上打印「讀取數據:#1發送數據線」 。但其他發送的數據將永遠不會被接收。有誰知道爲什麼?

任何幫助,將不勝感激。 在此先感謝。

編輯:我根據Papp的評論修改了我的代碼,然後按我的預期工作。 已收到所有已發信息。

這是否意味着我誤解了有關readLine()或canReadLine()的用法?

//  while(true){ 
//   if(pSerial.canReadLine()){ 
//    qDebug() << "CAN READ LINE"; 
//    nByte = pSerial.readLine(strBuf,sizeof(strBuf)); 
//    qDebug() << "Length: " << nByte; 
//    qDebug() << "Read data: " << strBuf; 
//   } 
//  } 

     pSerial.waitForReadyRead(TIMEOUT_MS); 
     QByteArray readData = pSerial.readAll(); 
     while (pSerial.waitForReadyRead(TIMEOUT_MS)) { 
      readData.append(pSerial.readAll()); 
     } 
     qDebug() << "Read data: " << readData; 

編輯第二次:下面的代碼也爲我工作。

while(true){ 
    if(pSerial.waitForReadyRead(TIMEOUT_MS) && pSerial.canReadLine()){ // I revised this line 
     qDebug() << "CAN READ LINE"; 
     nByte = pSerial.readLine(strBuf,sizeof(strBuf)); 
     qDebug() << "Length: " << nByte; 
     qDebug() << "Read data: " << strBuf; 
     qDebug() << "Error Message: " << pSerial.errorString(); 

    } 
} 
+0

流量控制?你禁用了嗎? –

+0

@JoeZ感謝您的評論。起初,我沒有給出關於流量控制的任何標誌。然後我添加了下面的代碼,但它對我不起作用。 pSerial.setFlowControl(QSerialPort :: SoftwareControl);或者pSerial.setFlowControl(QSerialPort :: NoFlowControl); –

+0

@yufit_in_Japan:我給了+1,但你有沒有試過在循環中讀取,如:QByteArray readData = serialPort.readAll(); (serialPort.waitForReadyRead(5000)) readData.append(serialPort.readAll());這樣的事情是否行得通,即我們能否確定它確實是一個readLine問題?另外,它在Unix上工作嗎? nByte第二次的價值是什麼?你是否檢查過errorString,以防萬一不成功,或者它是否成功爲零字符?順便說一下,你的代碼中的錯誤管理是相當潦草的。 – lpapp

回答

1

那是因爲你需要在這樣的循環讀取:

QByteArray readData = serialPort.readAll(); 
while (serialPort.waitForReadyRead(5000)) 
    readData.append(serialPort.readAll()); 

請參閱我添加到5.2的細節creadersync例子。您還可以檢查creaderasync示例進行非阻塞操作。公平起見,我們還沒有測試過readLine,但它在Unix上適用於我,所以在Windows上適用於其他人。

+0

這是如何幫助閱讀線?這個答案完全忽略了這一點。 –

+0

侵略性和無知的庫巴又回來了。 :(我真的沒有看到什麼「完全錯過了觀點」,實際上,OP得到了兩個不同的解決方案,應該在這個答覆中工作,他甚至對此感到高興,請在這個網站保持建設性的態度 – lpapp

+0

OP有麻煩你的答案根本沒有解決這個問題,你提供了一個不同的解決方案,忽略了線條閱讀的方面,當然這是有效的代碼,但是與線條閱讀沒有關係,在我的書中沒有提到。如何指明顯而易見的事實被認爲是侵略性的或無知的,我不知道。 –

0

您所犯的錯誤是期望在waitForReadyRead返回時接收所有發送的數據。當waitForReadyRead完成時,所有您保證的是有些數據可供閱讀。它可能只有一個字符,不一定是整條線。

從你最後修改的循環是幾乎正確的方式來做到這一點。您應該在單獨的循環中嵌套讀取行。下面的代碼是應該做,並與QIODevice語義同意:

while (pSerial.waitForReadyRead(TIMEOUT_MS)) { 
    while (pSerial.canReadLine()) { 
    qDebug() << "NEW LINE"; 
    QByteArray line = pSerial.readLine(); 
    qDebug() << "Length: " << line.size(); 
    qDebug() << "Read data: " << line; 
    qDebug() << "Error Message: " << pSerial.errorString(); 
    } 
} 
qDebug << "TIMED OUT"; 

注意,沒有這個代碼的,應在GUI線程甚至可以運行。理想情況下,您應該將其移至QObject,使用QIODevice(因此QSerialPort)發出的信號,並將該對象移至單獨的線程。

GUI線程有時會阻塞很長一段時間,通常不希望讓它干擾設備通信的及時性。同樣,您不希望設備超時阻止GUI線程。兩者同樣不好,並且是不良用戶體驗的非常常見的來源。 Qt使得多線程非常簡單 - 爲了您的用戶而使用它,並且正確地執行它。

+0

你真的讀過OP寫的麼?您的假設沒有任何意義,因爲寫入是在同步操作中發生的,甚至還有:OP僅獲取一行。我不明白這個答案的重點。更不用說,ui線程與非ui線程在這裏是一個紅色的鯡魚。這與canReadLine和readLine沒有任何關係,因爲它應該在兩種情況下都起作用。 – lpapp

+1

@LaszloPapp:問題是關於閱讀線條,在你的答案中沒有一個相關的提及閱讀線條。寫入是同步的事實並不意味着太多。僅僅因爲同步寫入「返回」並不意味着這些字節實際上已經在回送場景中移動到接收緩衝區。哎呀,這並不意味着他們已經離開了USB主機。提到的UI線程是相關的 - 我指出,不應該在那裏放置阻止代碼。它可能會或可能不適用,我提到它以防萬一。 –

+0

你真的不聽我的話,也不聽我的話,正如你寫的那樣,OP會收到一行(隨着你的回答誤認爲是隨機的)。最終,你的代碼更糟糕:它不會等待輸入超過某個超時,這不是OP想要的。此外,提及所有與現實問題無關的想象和理論案例是多餘的。 – lpapp