引自免费微信小程序:皆我百晓生
在您的代码中,serial1->readAll() 可能不会一次性读取到完整的44字节数据,因为它依赖于底层操作系统提供的缓冲区。当有新的数据到达时,它会填充这个缓冲区,但可能不会立即达到您期望的44字节。
为了解决这个问题,您可以考虑使用一个循环,不断从串口读取数据,直到接收到足够的字节。下面是一个示例代码,展示了如何在一个循环中累积接收到的数据,直到达到预期的大小:
// 在serialworker类中添加一个成员变量用于存储接收到的数据
class serialworker : public QThread {
public:
// ...
private:
quint8 receivedBuffer[45]; // 增加一个缓存数组,比实际大小多一位,用于容纳校验位或者其他额外信息
int receivedBytes = 0; // 用于记录已接收的字节数
};
// 更新RecvData函数,使其在接收到完整一帧之前保持循环
void serialworker::RecvData()
{
while (receivedBytes < 44) { // 44是您期望的一帧大小
QByteArray ba = serial1->read(44 - receivedBytes); // 仅尝试读取剩余的字节数
if (ba.isEmpty()) {
break; // 如果没有新数据,退出循环
}
for (int i = 0; i < ba.size(); ++i) {
receivedBuffer[receivedBytes + i] = ba[i];
}
receivedBytes += ba.size();
}
if (receivedBytes == 44) { // 当接收到完整一帧后
receivedBytes = 0; // 重置已接收的字节数
QString buffer = byteArrayToHexStr(QByteArray(receivedBuffer, 44)); // 提取并转换为十六进制字符串
emit ReceiveData(buffer);
} else {
// 处理未接收到完整一帧的情况,例如等待更多数据或重新开始循环
}
}
// 连接信号槽部分保持不变
connect(workserial, &serialworker::ReceiveData, this, [=](QString buffer) {
ui->textEdit->append(QString("串口 %1收到:").arg(ui->comboBox->currentText()));
ui->textEdit->append(buffer);
});
这样,您的程序将等待接收到完整的44字节数据后再发送信号,确保主线程只处理完整的一帧数据。注意,这里假设每帧数据都是44字节,如果有变化,请相应调整。此外,为了简化代码,这里假设您的串口通信不包含特定的帧结束标志,而是通过固定长度来判断一帧数据的边界。如果您使用的协议有特殊的帧结构,请根据实际情况调整代码。