Qt - 获取数据并通过串行连接转发它们

Posted

技术标签:

【中文标题】Qt - 获取数据并通过串行连接转发它们【英文标题】:Qt - get data and forward them on serial connection 【发布时间】:2014-03-27 17:33:26 【问题描述】:

我正在尝试开发一个简单的 Qt 应用程序。 在我按下“开始”按钮后,应用程序应该不断地从设备中检索数据(使用第三方库)并尽快通过串行连接转发它们。

到目前为止,我使用的(丑陋的)软件是一个控制台应用程序,它以顺序方式运行,并在主机提供数据帧后立即获取数据帧,使用以下循环:

    while(1)
    
          [...]
        while( MyClient.GetFrame().Result != Result::Success )
        
            Sleep( 200 );
            std::cout << ".";
        

          [... pack and send on serial]
    

我想知道在 Qt 中实现这一点的哪种方式更方便,以保持 GUI 响应,同时也尽可能减少 getFrame 和串行写入函数之间的延迟。

我应该使用 定时器触发的 SLOT 吗? QtConcurrent 命名空间QRunnable? 这些方法各自的主要优点和缺点是什么?

谢谢 求您的帮助!

【问题讨论】:

【参考方案1】:

由于现有库强制您轮询数据,因此唯一要做的就是在计时器上运行它。您可以选择执行此工作的对象是在主线程中运行,还是在工作线程中运行。无需使用 Qt Concurrent 或 QRunnable - 使用 QObject 让生活变得更简单,因为您可以轻松地向 GUI 提供反馈。

例如,对客户的 API 做出一些假设:

class Worker : public QObject 
  Client m_client;
  QSerialPort m_port;
  QBasicTimer m_timer;

  void processFrame() 
    if (m_client.GetFrame().Result != Result::Success) return;
    QByteArray frame = QByteArray::fromRawData(
      m_client.GetFrame().Data, m_client.GetFrame().Size);
    ... process the frame
    if (m_port.write(frame) != frame.size()) 
      ... process the error
    
  
  void timerEvent(QTimerEvent * ev) 
    if (ev->timerId() == m_timer.timerId()) processFrame();
  
public:
  Worker(QObject * parent = 0) : QObject(parent) 
  Q_SLOT bool open(const QString & name) 
    m_port.close();
    m_port.setPortName(name);
    if (!m_port.open(name)) return false;
    if (!m_port.setBaudRate(9600)) return false;
    if (!m_port.setDataBits(QSerialPort::Data8)) return false;
    ... other settings go here
    return true;
  
  Q_SLOT void start()  m_timer.start(200, this); 
  Q_SLOT void stop()  m_timer.stop(); 
  ...


/// A thread that's always safe to destruct
class Thread : public QThread 
  using QThread::run; // lock the default implementation
public:
  Thread(QObject * parent = 0) : QThread(parent) 
  ~Thread()  quit(); wait(); 
;

int main(int argc, char ** argv) 
  QApplication app(argc, argv);
  Worker worker;
  Thread thread; // worker must be declared before thread!
  if (true) 
    // this code is optional, disabling it should not change things
    // too much unless the client implementation blocks too much
    thread.start();
    worker.moveToThread(&thread);
  

  QPushButton button("Start");
  QObject::connect(&button, &QPushButton::clicked, [&worker]
    // Those are cross-thread calls, they can't be done directly
    QMetaObject::invoke(&worker, "open", Q_ARG(QString, "COM1");
    QMetaObject::invoke(&worker, "start");
  );
  button.show();

  return app.exec(argc, argv);

【讨论】:

以上是关于Qt - 获取数据并通过串行连接转发它们的主要内容,如果未能解决你的问题,请参考以下文章

如何在 QT 中查看和存储来自设备的数据?

QT软件开发: QProcess启动进程完成交互并获取输出

使用Nodejs获取博客园博客数据并处理转发

如何获取qt动态生成控件的数据

Hyper-V:通过命名管道连接 VM 会丢失数据

qt串口设置停止位出现