QSerialPort 可以读取超过 512 字节的数据吗?

Posted

技术标签:

【中文标题】QSerialPort 可以读取超过 512 字节的数据吗?【英文标题】:Can QSerialPort read more than 512 bytes of data? 【发布时间】:2016-04-13 08:05:49 【问题描述】:

我想使用 QSerialPort 读取从设备传输的数据。设备每次传输 4000 个数据字节的帧。我尝试使用以下简单代码

QSerialPort *serialPort;
char receivedData[4000];
int numRead = 0;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)

    ui->setupUi(this);

    /* Initialize serial port*/
    serialPort = new QSerialPort(this);
    QString portName = "COM6";
    qint32 baudRate = 460800;
    serialPort->setPortName(portName);
    serialPort->setBaudRate(baudRate);
    serialPort->setDataBits(QSerialPort::Data8);
    serialPort->setParity(QSerialPort::NoParity);
    serialPort->setStopBits(QSerialPort::OneStop);
    serialPort->setFlowControl(QSerialPort::NoFlowControl);
    serialPort->setReadBufferSize(4000);
    if (!serialPort->open(QIODevice::ReadOnly)) 
        qDebug() << "Cannot open comport";
    
    connect(serialPort, SIGNAL(readyRead()), this, SLOT(serialReceived()));


void MainWindow::serialReceived()

    numRead = serialPort->read(receivedData, 4000);
    serialPort->flush();

问题是:它总是显示只读取了 512 个数据字节。如何读取整个 4000 字节数据帧? (当我使用 Matlab 读取这 4000 字节的帧时,它工作正常)

【问题讨论】:

见this answer。您必须创建自己的缓冲区来读取数据,直到满足您期望的某个特定大小。您也可以使用QSerialPort::bytesAvailable 方法检查可用的字节数。 嗨,我使用循环检查QSerialPort::bytesAvailable,它总是显示512字节。 您是否在两次检查之间读取数据? 你是对的。现在想起来,这不是正确的做法。但是我不知道应该把QSerialPort::bytesAvailable放在哪里,因为我不知道程序要等到readReady发出? 您可以使用 Ilya 的建议,读取您自己的缓冲区中的所有数据,一旦该缓冲区达到 4000 字节或更多,就从您的缓冲区中删除前 4000 个字节并对这些数据进行处理。我认为可行的另一个选择是,如果您利用QSerialPorts 的内部缓冲区。当readyRead 发出时,检查bytesAvailable。如果小于 4000,则什么都不做,如果大于或等于 4000,则读取 4000 字节,直到可用的字节小于 4000。 【参考方案1】:

没有限制,但您不一定会在单个块中接收所有数据。 您必须继续收听,直到获得等待的字节数(或超时)。

void MainWindow::serialReceived()

    receivedData.append(serialPort->readAll());
    if(receivedData.size() >= 4000) 
       // we're full
    

【讨论】:

【参考方案2】:

您通常必须在循环中读取数据(以确保您得到所有​​数据),这是示例代码的 sn-p 这相当于您的 serialReceived() 函数,除了它使用 @987654321 发出数据@给正在听的人...

void QSerialPortReader::handleReadyRead()

    QByteArray newData;

    // Get the data
    while (mp_serialPort->bytesAvailable())
    
        newData.append(mp_serialPort->readAll());
    
    emit rxDataReady(newData);

编辑

虽然我没有做任何最大尺寸检查...但是如果您需要它,添加它是微不足道的(即只需使用 read(..., spaceAvail) 而不是 readAll 然后递减 spaceAvail...

【讨论】:

嗨,我尝试了以下代码,但它只导致读取了 60 个字节。我不明白为什么? void MainWindow::serialReceived() &lt;br/&gt; &lt;br/&gt; while (serialPort-&gt;bytesAvailable()) &lt;br/&gt; &lt;br/&gt; readData.append(serialPort-&gt;readAll()); &lt;br/&gt; &lt;br/&gt; 可用字节是否显示超过 60 个字节? (也许添加一个调试行)。 readReady 是否还会被多次调用?要检查的另一件事,不是 100% 确定这是否是一个问题,但看起来您正在同一个线程中运行所有这些。在你的 connect() 函数中使用Qt::QueuedConnection 可能更安全(它是可选的第 5 个参数)。在您的代码中,我不知道如果第二个 readReady 在第一个完成之前进入会发生什么。

以上是关于QSerialPort 可以读取超过 512 字节的数据吗?的主要内容,如果未能解决你的问题,请参考以下文章

重新实现 QSerialPort canReadLine() 和 readLine() 方法

一次从文件中读取 512 个字节并检查里面有啥?

Qt 小部件的 QSerialPort 读数刷新太快

Qt串口通信开发之QSerialPort模块

第六课 突破512字节的限制 上

从内存中读取1024字节的数据,8086至少要读 512 次,80386至少要读 256 次。《汇编语言(第三版习题笔记)》