2016-06-29 5 views
0

Ich verwende Qt, um ein serielles Gerät zu steuern. Wenn ich einen Befehl an mein serielles Gerät sende, mache ich etwas wie serial->write("command \r\n"). Ich habe einen Knopf gemacht, der den Text in einem einfachen Text-Widget in die Antwort des seriellen Ports ändert. Um die Antwort der seriellen Schnittstelle zu erhalten, verwende ich serial->readAll(). Das Problem ist, dass es die zweitletzte Antwort zeigt und nicht die, die ich erwartet habe. Hat Qt eine Art Puffer, der diese Antwort hält?readAll() von QSerialPort enthält nicht die letzte gesendete Antwort

EDIT ich verpfuschten es durch Rekursion und die Saiten

Antwort

3

Sie erhielt im Vergleich könnte readAll, bevor die Antwort zur Verfügung anrufen. Sie sollten Ihren Code an das readyRead Signal anhängen, um jedes Mal benachrichtigt zu werden, wenn ein neuer Datenblock zum Lesen bereit ist. Denken Sie daran, dass readyRead mit einer beliebigen Anzahl von Bytes zum Lesen ausgegeben werden kann - mindestens wird es nur ein Byte sein. Sie können nicht erwarten, dass die Daten in einer bestimmten Weise chunked/blockiert werden, da der serielle Port nicht als nachrichtenbasiertes Kommunikationsgerät fungiert. Ihr Empfängercode muss in der Lage sein, die Daten aus kleinen Teilen zusammenzusetzen und entsprechend zu handeln, wenn alle benötigten Daten vorhanden sind.

Angenommen, die Antworten des Geräts haben eine feste, bekannte Länge. Sie möchten nur reagieren, wenn eine vollständige Antwort eingetroffen ist. Zum Beispiel:

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

Danke das war eine sehr hilfreiche Antwort! – jxb458

Verwandte Themen