来自QSerialPort的readAll()不包含最后发送的响应 [英] readAll() from QSerialPort doesn't include the last response sent

查看:70
本文介绍了来自QSerialPort的readAll()不包含最后发送的响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Qt控制串行设备.如果我向串行设备发送命令,则会执行 serial-> write("command \ r \ n")之类的操作.我做了一个按钮,将纯文本小部件内的文本更改为串行端口的响应.为了获得串行端口的响应,我使用了 serial-> readAll().问题在于它显示的是倒数第二个响应,而不是我所期望的.Qt是否有某种缓冲区可以保留此响应?

I'm using Qt to control a serial device. If I send a command to my serial device, I do something like serial->write("command \r\n"). I made a push button which changes the text inside a plain text widget to the response of the serial port. To get the response of the serial port, I'm using serial->readAll(). The problem is it shows the 2nd to last response rather than the one I was expecting. Does Qt have some sort of buffer which is keeping hold of this response?

编辑我通过使用递归对其进行了修改,并比较了收到的字符串

EDIT I botched it by using recursion and compared the strings recieved

推荐答案

在响应可用之前,您可能正在调用 readAll .您应该将代码挂接到 readyRead 信号上,以便在每次准备读取新的数据块时收到通知.请记住, readyRead 可以与任何数量的可用字节一起发出-至少只有一个字节.您不能指望数据会以任何特定方式进行分块/阻止,因为串行端口不充当基于消息的通信设备.您的接收器代码必须能够从小块中整理数据,并在获得所需的所有数据时采取相应的行动.

You might be calling readAll before the response is available. You should hook your code to the readyRead signal to be notified each time new chunk of data is ready to be read. Keep in mind that readyRead can be emitted with any number of bytes available to read - at a minimum, it'll be just one byte. You can't expect the data to be chunked/blocked in any particular way, since the serial port doesn't act as a message-based communication device. Your receiver code must be able to piece the data together from small chunks and act accordingly when it got all the data it needs.

例如,假设设备响应具有固定的已知长度.您只想在收到完整响应后做出反应.例如:

For example, suppose that the device responses have a fixed, known length. You'd only want to react when a complete response has arrived. E.g.:

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 :("; });

这篇关于来自QSerialPort的readAll()不包含最后发送的响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆