我必须在工作中驾驶激光,为此我需要与 RS232 中的串行端口通信。由于您在使用激光时必须小心,因此您需要不断读取激光状态(温度、功率等...),为此您必须每 1 或 2 秒发送大量命令(~20) .
我使用 Qt 类QserialPort,我的问题是,当我发送所有命令时,我阻塞了 GUI,程序变得不可用。我阅读了很多关于 QSerialPort 以及如何使用它的内容,例如:Blocking Master、Blocking Slave、Async reader、Terminal 等。我仍然无法弄清楚。
首先我想使用线程,但这个人的回答说这是个坏主意。然后,我尝试不使用线程,但得到了相同的结果。
我想要的是一种与激光通信的方式,它不会使整个程序等待发送的答案以及处理相应的答案。我发送我的第一个命令,激光回答,我处理答案,然后我发送第二个命令,等等......所有这些都在后台。
我当前的实现是基于线程的,但我还有一个没有线程的实现。
我有用于 GUI的MainWindow类,一个Laser类,它知道如何为激光编写消息以理解并理解激光的答案,以及一个LaserThread类打开与串行端口的连接,写入和读取。
要发送命令,我会:
void LaserThread::writeData(const QByteArray &data)
{
while(m_serialPort->waitForReadyRead(200)){} //Timeout is 200ms
m_serialPort->write(data);
}
这意味着我在发送新命令之前等待收到答复。我尝试使用 waitForBytesWritten但无法获得预期结果。我必须连续调用这个函数 20 次。
阅读答案:
void LaserThread::readFromFPGA()
{
if (m_serialPort->bytesAvailable()>0) {
if (m_serialPort->waitForReadyRead(20)){
QByteArray response = m_serialPort->readAll();
if(response.size()==0)
return;
qDebug() << "response" << toDebug(response); //transforms bytes to QString
if(m_laser->checkMessage(response)) //check msg conformity
m_laser->handleMessage(response); //process it
}
}
}
现在我的两个问题是:
- 或者,我等待发送新命令的时间过长,并且 UI 被冻结
- 或者,我不会等待太多,发送 25 条消息,只得到一个回复。
在不冻结程序的情况下不断与串行端口通信(异步或同步)的正确方法是什么?