我尝试使用Qt和QSerialPort类编程串口。我有一个连接到我的PC的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内部的缓冲区中。但我想按如下方式使用串口:
端口 - →写(" MEAS \ n"?); QString reply = receive_reply(); //等到收到\ n或发生超时
答案 0 :(得分:1)
我会试试这个:
port->write(QString("meas?\n").toLocal8Bit().data());
port->flush();
port->waitForBytesWritten();
port->waitForReadyRead();
QString rxdata;
while(!rxdata.endsWith("\n"))
{
rxdata.append(port->readAll());
}
答案 1 :(得分:0)
我稍微扩展了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冻结,我也实现了超时。