称重串口数据报文解析
十六进制报文解析
报文 1:
报文 2:
08 20 20 20 20 20 30 2E 30 36 0D
08 20 20 20 35 30 30 2E 31 5C 0DASCII 解码规则:0x20= 空格,0x0D= 回车\r,0x2E= 小数点.
报文 1 拆解
表格
| HEX | 08 | 20 | 20 | 20 | 20 | 20 | 30 | 2E | 30 | 36 | 0D |
|---|---|---|---|---|---|---|---|---|---|---|---|
| ASCII | 退格 BS | 空格 | 空格 | 空格 | 空格 | 空格 | 0 |
. |
0 |
6 |
\r |
有效字符串:
数值:0.06
0.06\r(前面 5 个空格)
报文 2 拆解
表格
| HEX | 08 | 20 | 20 | 20 | 35 | 30 | 30 | 2E | 31 | 5C | 0D |
|---|---|---|---|---|---|---|---|---|---|---|---|
| ASCII | 退格 BS | 空格 | 空格 | 空格 | 5 |
0 |
0 |
. |
1 |
\ |
\r |
有效字符串:
500.1\\r(前面 3 个空格)⚠️末尾是反斜杠\,不是数字,大概率是仪表 / 串口输出乱码、校验位或者打印错误;数字部分:500.1
补充说明
- 首字节
0x08是 BS 退格控制字符,很多串口仪表、称重传感器、数显仪输出会带这个前缀,一般业务解析直接忽略 0x08 即可。 0x0D是回车结束符,作为一帧结束标志。- 报文 2 末尾
0x5C(\)属于异常字符,正常数值报文不该出现,常见原因:- 串口波特率 / 校验位不匹配导致接收乱码
- 设备本身协议帧尾不是纯数字
- 抓包字节截取错位
C/C++ 简单解析思路
跳过首字节
0x08,过滤0x20空格,读到0x0D停止,中间字节转 ASCII 字符串,再atof()转浮点数。/** * @brief 解析称重仪表ASCII报文 * data: 串口收到原始字节数组 * outWeight: 输出重量 * return true解析成功 */ bool parseWeight(const QByteArray &data, double &outWeight) { // 找帧结束符 0x0D int idx = data.indexOf('\r'); if(idx < 0) return false; QByteArray frame = data.left(idx); frame.remove((char)0x08); //去掉开头0x08退格 frame = frame.trimmed(); //去除前后空格 if(frame.isEmpty()) return false; //过滤非数字、小数点字符(处理乱码如0x5C反斜杠) QByteArray valid; for(char ch : frame){ if(isdigit(ch) || ch == '.'){ valid.append(ch); } } if(valid.isEmpty()) return false; bool ok; double w = valid.toDouble(&ok); if(!ok) return false; outWeight = w; return true; }
使用:
//串口readyRead槽函数 void onSerialReadyRead() { static QByteArray buf; buf += serial->readAll(); //循环处理所有完整帧(以\r分隔) while(true){ int pos = buf.indexOf('\r'); if(pos == -1) break; QByteArray oneFrame = buf.mid(0, pos+1); buf = buf.mid(pos+1); //剩余缓存 double weight; if(parseWeight(oneFrame, weight)){ qDebug() << "当前重量:" << weight; } } }
欢迎讨论,相互学习。
cdtxw@foxmail.com

浙公网安备 33010602011771号