Qt串行端口数据接收

Qt SerialPort data reception

本文关键字:数据 串行端口 Qt      更新时间:2023-10-16

我尝试使用Qt和QSerialPort类对串行端口进行编程。我有一个USB/串行转换器连接到我的电脑,外部设备连接到串行端口。可以查询设备(例如"ver?n""meas?n"( 并用字符串回复;例如,对"ver?n"的答复可以是"version 1.0"的,或者对"meas?n"的答复可以是逗号分隔的测量列表,列表的长度事先是未知的。我唯一知道的是,每个回复都由CR + LF终止。

当单击 GUI 上的按钮时,我想发送特定请求,等待完整响应,然后处理数据。

我已经为 readyRead 信号实现了一个插槽,这工作正常,但问题是这是完全异步的。如何解决我的问题?

我已经尝试了以下方法:

port->write(QString("meas?n").toLocal8Bit().data());
port->flush();
port->waitForBytesWritten();
port->waitForReadyRead();
QString rxdata = port->readLine();

但是,这并不可靠,因为如果我的外部设备没有足够快地提供答案,QSerialPort 内部的超时就会过期,并且根本不返回任何数据,或者有时,我只得到部分数据(我认为这也是由于内部超时(。

接下来,我尝试使用信号和插槽方法。我将QSerialPort readyRead信号连接到以下插槽

void onReadyRead()
{
static QString buffer;
while(port->bytesAvailable())
{
buffer = buffer.append(port->readAll());
if(buffer.endsWith("n"))
{
// the reply is received completely
}
}
}

这确实可以正确接收完整数据,但不幸的是,这是一种异步方法,回复存储在 onReadyRead 内部的缓冲区中。但是我想按如下方式使用串行端口:

port->write("meas?"(; QString 回复 = receive_reply((;等待 收到或发生超时

我会试试这个:

port->write(QString("meas?n").toLocal8Bit().data());
port->flush();
port->waitForBytesWritten();
port->waitForReadyRead();
QString rxdata;
while(!rxdata.endsWith("n"))
{
rxdata.append(port->readAll());
}

我已经扩展了p-a-o-l-o答案:

QString buf;
QTime start = QTime::currentTime();
port->write("meas?n");
port->flush();
port->waitForBytesWritten();
buf.clear();
while(!buf.endsWith("n"))
{
if(!port->waitForReadyRead(50))
break;
buf.append(port->readAll());
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);

int elapsed = start.msecsTo(QTime::currentTime());
qDebug() << elapsed;
if(elapsed > 10000)
{
buf.clear();
port->clear();
break;
}
}
return buf.trimmed();

我还添加了 processEvents(( 调用以防止 GUI 冻结,并且我还实现了超时。