Qt中通过SerialPort串口发送十六进制数据及代码异常排查
问题原因
你代码里的逻辑错误直接导致数据无法正确发送,核心问题有三个:
- 发送逻辑顺序写反:你第一次调用
serialPort->write()时,send_data是空数组,要发送的0xAA是在write执行完之后才追加到数组里,第一次发送根本没有带上目标字节。后续第二次调用write虽然追加了0xAA,但没有做发送状态校验和等待,数据大概率滞留在缓冲区没有实际发出。 - 长度计算完全错误:
sizeof(send_data)计算的是QByteArray类对象本身占用的栈内存大小(固定值,和数组里存了多少有效数据无关),不是待发送数据的实际长度,QByteArray存储的有效数据长度必须调用.size()方法获取。 - 异步发送丢数据:Qt串口的
write()方法是异步接口,调用后数据只是被放到了发送缓冲区,不会立刻从串口发出,如果write之后马上执行关闭串口、清空缓冲区等操作,缓冲区里的数据会直接丢失,对端自然收不到。
正确的十六进制数据发送实现
实现步骤
- 先把所有待发送的十六进制字节按顺序填充到QByteArray中,所有数据填充完成后再调用write接口
- 传入write接口的数据长度参数,使用QByteArray的
.size()方法获取,禁止用sizeof计算容器类的有效数据长度 - write调用后,调用
waitForBytesWritten()等待数据实际从串口发出,或者绑定bytesWritten信号确认发送状态,避免缓冲区数据丢失 - 提前确认串口配置(波特率、数据位、停止位、校验位、流控)和对端完全匹配,参数不匹配会导致对端收不到有效数据或解析乱码
参考代码
QByteArray send_data; // 所有待发送十六进制数据必须在write调用前填充完成 send_data += static_cast<char>(0xAA); // 多字节数据按顺序追加即可,示例: // send_data += static_cast<char>(0x55); // send_data += static_cast<char>(0x01); if(serialPort->isWritable()) { qDebug() << "串口可写,开始发送数据"; qint64 writeRet = serialPort->write(send_data); if(writeRet == -1) { qDebug() << "发送出错:" << serialPort->errorString(); return; } // 等待数据实际写入串口,超时时间设置1000ms即可覆盖绝大多数场景 if(!serialPort->waitForBytesWritten(1000)) { qDebug() << "发送超时:" << serialPort->errorString(); } else { qDebug() << "发送完成,实际发送字节数:" << writeRet; } }
额外注意事项
- 连续发送多帧数据时,不要无间隔连续调用write,等上一帧发送完成(waitForBytesWritten返回成功或者收到bytesWritten信号)再发送下一帧,避免缓冲区溢出导致粘包、丢包
- 如果要发送的十六进制数据是字符串格式(比如"AA 55 01"),可以直接调用
QByteArray::fromHex()方法把十六进制字符串转成字节数组,不需要自己逐字节强转
内容的提问来源于stack exchange,提问作者sam
相关产品推荐
相关产品推荐

