Получение данных Qt SerialPort - PullRequest
0 голосов
/ 23 мая 2018

Я пытаюсь запрограммировать последовательный порт, используя Qt и класс QSerialPort.У меня есть USB / Serial конвертер, подключенный к моему ПК, и к последовательному порту подключено внешнее устройство.Устройство может быть запрошено (например, "ver?\n" или "meas?\n") и отвечает строками;например, ответ на "ver?\n" может быть "version 1.0" или ответ на "meas?\n" может быть разделенным запятыми списком измерений, длина списка заранее неизвестна.Единственное, что я знаю, это то, что каждый ответ завершается символом CR + LF.

Когда нажимается кнопка в моем графическом интерфейсе, я хочу отправить конкретный запрос, дождаться полного ответа и затем обработать данные..

Я уже реализовал слот для сигнала readyRead, он работает нормально, но проблема в том, что он полностью асинхронный.Как я могу решить свою проблему?

Я уже попробовал следующее:

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

Однако это не работает надежно, потому что, если мое внешнее устройство не дает ответ достаточно быстро,Внутренний тайм-аут для QSerialPort истекает, и никакие данные не возвращаются вообще, или иногда я получаю только частичные данные (я думаю, это также из-за внутреннего тайм-аута).

Затем я попытался использовать сигнал ислот подход.Я подключил сигнал ReadyRead QSerialPort к следующему слоту

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 ("measure? \ N");QString reply = receive_reply ();// дождемся \ n получения или тайм-аута

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Я немного расширил ответ paolo:

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 (), чтобы предотвратить зависание графического интерфейса, и я также реализовал тайм-аут.

0 голосов
/ 23 мая 2018

Я бы попробовал это:

port->write(QString("meas?\n").toLocal8Bit().data());
port->flush();
port->waitForBytesWritten();
port->waitForReadyRead();
QString rxdata;
while(!rxdata.endsWith("\n"))
{
    rxdata.append(port->readAll());
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...