2016-06-29 25 views
0

我正在使用Qt來控制串行設備。如果我發送命令到我的串口設備,我會做類似serial->write("command \r\n")的操作。我製作了一個按鈕,它將純文本小部件中的文本更改爲串行端口的響應。爲了得到串口的響應,我使用了serial->readAll()。問題在於它顯示了第二個到最後一個響應,而不是我期待的那個。 Qt是否有某種保持這種響應的緩衝區?從QSerialPort的readAll()不包括最後發送的響應

編輯 我把事情弄糟了通過使用遞歸和比較字符串收到

回答

3

你可能會調用readAll響應可用之前。您應該將您的代碼掛接到readyRead信號,以便每次準備好讀取新數據塊時都會收到通知。請記住,readyRead可以以可讀取的任意數量的字節發送 - 至少它只會是一個字節。您不能期望數據以任何特定的方式被分塊/阻塞,因爲串行端口不會充當基於消息的通信設備。您的接收器代碼必須能夠將數據從小塊組合在一起,並在獲取所需的所有數據時採取相應措施。

例如,假設設備響應具有固定的已知長度。您只想在完整回覆到達時作出反應。例如:

class Protocol : public QObject { 
    Q_OBJECT 
    QBasicTimer m_timer; 
    QPointer<QIODevice> m_port; 
    int m_responseLength = 0; 
    int m_read = 0; 
    void timerEvent(QTimerEvent * ev) override { 
     if (ev->timerId() != m_timer.timerId()) return; 
     m_timer.stop(); 
     emit timedOut(); 
    } 
    void onData() { 
     m_read += m_port->bytesAvailable(); 
     if (m_read < m_responseLength) 
     return; 
     m_timer.stop(); 
     emit gotResponse(m_port->read(m_responseLength)); 
     m_read -= m_responseLength; 
     m_responseLength = 0; 
    } 
public: 
    Q_SIGNAL void gotResponse(const QByteArray &); 
    Q_SIGNAL void timedOut(); 
    Q_SLOT void sendCommand(const QByteArray & cmd, int responseLength, int cmdTimeout) { 
     m_responseLength = responseLength; 
     m_port->write(cmd); 
     m_timer.start(cmdTimeout, this); 
    } 
    explicit Protocol(QIODevice * port, QObject * parent = nullptr) : 
     QObject(parent), m_port(port) { 
     connect(m_port, &QIODevice::readyRead, this, &Protocol::onData); 
    } 
}; 

... 
Protocol protocol(0,0); 
protocol.sendCommand({"foo"}, 10, 500); 
QMetaObject::Connection cmd1; 
cmd1 = QObject::connect(&protocol, &Protocol::gotResponse, [&]{ 
    QObject::disconnect(cmd1); 
    qDebug() << "got response to foo"; 
}); 
QObject::connect(&protocol, &Protocol::timedOut, []{ qDebug() << "timed out :("; }); 
+0

感謝這是一個非常有幫助的迴應! – jxb458