Qt SerialPort数据接收

时间:2018-05-23 06:58:44

标签: c++ qt serial-port

我尝试使用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或发生超时

2 个答案:

答案 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冻结,我也实现了超时。