仪器设备卖出去,客户要配套软件看数据、出报告——这类上位机看着小,坑全在通信上。串口数据粘包分包、TCP断线不自知、指令发出去石沉大海,每一个都是现场投诉的重灾区。这篇拿一个老化测试柜的真实项目,把Qt串口/TCP通信的落地细节掰开讲。

串口和TCP,仪器配套软件该选哪条路?

先看设备端给了什么。老式仪器、试验箱基本是RS232/RS485串口,新一点的带网口。我的做法是两条通道都做,协议层统一:QSerialPort和QTcpSocket只是收发字节的"管道"不同,上面的组帧、拆包、校验逻辑共用同一套代码。现场用串口线就连串口,接了车间网络就走TCP,客户自己切,软件不挑。

串口参数(波特率、数据位、停止位、校验)和网口参数(IP、端口)全部放配置界面,别写死。仪器行业有个特点:不同批次设备的默认参数可能不一样,写死一个值,售后电话能被打爆。

readyRead 收到的数据,为什么拼不成完整帧?

新手最容易栽的跟头:以为readyRead信号来一次就是一帧数据。根本不是。串口和TCP都是字节流,一次信号可能给你半帧,也可能一次塞给你两帧半。正确姿势是维护一个接收缓冲区,来多少append多少,然后用状态机循环拆包:找帧头→读长度→收齐载荷→校验CRC/校验和→取出完整帧,剩余字节留在缓冲区等下次。

协议本身也要选靠谱的。定长帧最简单但死板;推荐"帧头+长度+载荷+校验"的变长帧。CRC16比累加和靠谱,仪器现场电磁环境复杂,一个错误字节没拦住,写进报告就是事故。拆包状态机还要处理帧头丢失的情况——同步失败时逐字节滑动找下一个帧头,不能卡死。

指令发出去没回应,干等还是重发?

仪器通信是典型的请求-应答模式:上位机发查询指令,仪器回数据。必须配套超时重发机制:发完指令记下序号和时间戳,定时器里检查,比如500毫秒没应答就重发,重发三次还失败,判定通信异常并提示。连续超时和偶发超时要区分对待——偶发一次重发成功了,界面上别报警吓人;连续失败才亮红灯。

还有个细节:查询指令别多线程乱发。一个仪器一个会话,采集定时器周期触发,上一轮应答没回来,下一轮查询就排队等,否则应答和指令错位,解析出来的温度张冠李戴,这种bug查起来能要人命。

TCP通道,断了怎么自己发现、自己恢复?

TCP比串口多一层麻烦:网线拔了、交换机重启,软件不能傻等。socket的disconnected信号接上,状态机切到"未连接",界面灰显;后台起重连定时器,指数退避(1秒、2秒、4秒)反复尝试,连上了自动恢复采集。应用层再加心跳——半开连接(网线被对端悄悄断掉)TCP自己是发现不了的,每隔几秒发个轻量查询,没应答就当断线处理。

说实话,串口这边也别大意:USB转串口被碰松,Qt里串口报错后要close再重新open,不能指望它自己好。通道句柄统一由通信管理器持有,生命周期跟着软件走,别在某个按钮槽函数里open完就不管了。

数据上来之后,业务怎么接住?

通信层只管把"干净的帧"交出来,后面的事分层处理:解析出工程值(原始值换算温度、电压)→ 写本地SQLite留底 → 信号通知界面刷新曲线。试验过程数据是要出报告的,落库这一步不能省,通信中断期间的数据缺口也要在报告里标出来,别让曲线假装连续。

我之前做的那个老化测试柜项目,8个通道同时跑168小时老化试验,485总线挂了8台柜子。上线第一周就遇到过一次:现场变频器启动时干扰485总线,偶发字节错位,全靠CRC校验把坏帧拦了下来,重发后数据补齐。要是当初图省事务了校验,这批老化报告的可信度就得打问号。

做仪器配套软件,先验证哪一步?

行动建议:开发板都不用等,先写个十几行的串口/TCP回环工具,把组帧、拆包、CRC、超时重发这套逻辑在PC上自测透——自发自收,人为丢字节、粘包、延迟,状态机怎么折腾都不崩,再接真仪器。通信底座稳了,业务界面做起来才踏实。