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() <br/> <br/> while (serialPort->bytesAvailable()) <br/> <br/> readData.append(serialPort->readAll()); <br/> <br/>
可用字节是否显示超过 60 个字节? (也许添加一个调试行)。 readReady 是否还会被多次调用?要检查的另一件事,不是 100% 确定这是否是一个问题,但看起来您正在同一个线程中运行所有这些。在你的 connect() 函数中使用Qt::QueuedConnection
可能更安全(它是可选的第 5 个参数)。在您的代码中,我不知道如果第二个 readReady 在第一个完成之前进入会发生什么。以上是关于QSerialPort 可以读取超过 512 字节的数据吗?的主要内容,如果未能解决你的问题,请参考以下文章
重新实现 QSerialPort canReadLine() 和 readLine() 方法
从内存中读取1024字节的数据,8086至少要读 512 次,80386至少要读 256 次。《汇编语言(第三版习题笔记)》