c++ - readyRead() 在 Qt 中如何工作?

标签 c++ qt qtcore qtserialport qiodevice

这是我在这个网站上的第一个问题!

我在从一个 COM 端口读取数据时遇到了一些问题,我从另一个 COM 端口发送了一条完整的消息,当我用 Qt 接收它时,它总是被分成多个子消息。

void SerialPortReader::init()
{
    connect(m_serialPort, SIGNAL(readyRead()), this, SLOT(readData()));
}   

void SerialPortReader::readData()
{
//    m_serialPort->waitForReadyRead(200);
    QByteArray byteArray = m_serialPort->readAll();
    qDebug() << byteArray;

    if(byteArray.startsWith(SOF) && byteArray.endsWith(EOF_LS)
        && byteArray.size() >= MIN_SIZE_DATA) {
    decodeData(byteArray.constData());
    } else {
        qDebug() << "LIB SWCom : Unvalid trame !";
    }
}

发送的消息有 25 或 27 字节长,如果我使用 Putty 或 super 终端读取它们,我没有问题。 另外如果我用2个模拟串口COM来通讯,就没有这个问题了... 它只发生在 Qt 阅读系统和 2 个物理 COM 端口......

我想我不知道 readyRead 信号何时准确发出...

我很困惑,在此先感谢您的帮助!

最佳答案

documentation其实很清楚:

void QIODevice::readyRead() [signal]

This signal is emitted once every time new data is available for reading from the device. It will only be emitted again once new data is available, such as when a new payload of network data has arrived on your network socket, or when a new block of data has been appended to your device.

readyRead() is not emitted recursively; if you reenter the event loop or call waitForReadyRead() inside a slot connected to the readyRead() signal, the signal will not be reemitted (although waitForReadyRead() may still return true).

Note for developers implementing classes derived from QIODevice: you should always emit readyRead() when new data has arrived (do not emit it only because there's data still to be read in your buffers). Do not emit readyRead() in other conditions.

这意味着并不能真正保证有多少数据可供阅读,只是有一些可用。

如果您希望读取的数据多于一次读取的数据,您可以选择超时值和/或 readyRead。这取决于您要实现的目标。

参见 command line async reader example我不久前也为这个操作写过:

#include "serialportreader.h"

#include <QCoreApplication>

QT_USE_NAMESPACE

SerialPortReader::SerialPortReader(QSerialPort *serialPort, QObject *parent)
    : QObject(parent)
    , m_serialPort(serialPort)
    , m_standardOutput(stdout)
{
    connect(m_serialPort, SIGNAL(readyRead()), SLOT(handleReadyRead()));
    connect(m_serialPort, SIGNAL(error(QSerialPort::SerialPortError)), SLOT(handleError(QSerialPort::SerialPortError)));
    connect(&m_timer, SIGNAL(timeout()), SLOT(handleTimeout()));

    m_timer.start(5000);
}

SerialPortReader::~SerialPortReader()
{
}

void SerialPortReader::handleReadyRead()
{
    m_readData.append(m_serialPort->readAll());

    if (!m_timer.isActive())
        m_timer.start(5000);
}

void SerialPortReader::handleTimeout()
{
    if (m_readData.isEmpty()) {
        m_standardOutput << QObject::tr("No data was currently available for reading from port %1").arg(m_serialPort->portName()) << endl;
    } else {
        m_standardOutput << QObject::tr("Data successfully received from port %1").arg(m_serialPort->portName()) << endl;
        m_standardOutput << m_readData << endl;
    }

    QCoreApplication::quit();
}

void SerialPortReader::handleError(QSerialPort::SerialPortError serialPortError)
{
    if (serialPortError == QSerialPort::ReadError) {
        m_standardOutput << QObject::tr("An I/O error occurred while reading the data from port %1, error: %2").arg(m_serialPort->portName()).arg(m_serialPort->errorString()) << endl;
        QCoreApplication::exit(1);
    }
}

在这种情况下,命令行阅读器示例将获取一次性传递的任何数据,但它不保证长度或任何内容。

另外,请注意,您的评论背后的同步 API 与您询问的异步 API 并没有多大意义。我在这里指的是 m_serialPort->waitForReadyRead(200);

关于c++ - readyRead() 在 Qt 中如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26612852/

相关文章:

c++ - QSharedMemory::create() 问题

c++ - 同时标记多个字符串

c++ - C++ 客户端中的 WSAGetLastError 10038

qt - QMainWindow 设置 frameSize

c++ - 没有 x 服务器的 QtTest 控制台应用程序

c++ - Qt 信号槽不工作

c++ - 如何通过网络传输opencv Mat?

c++ - 在字符数组上使用 next_permutation

C++ Travis CI 和 Qt5

javascript - 如何通过 Qt 访问 javascript 中的数据?