称重串口数据报文解析

十六进制报文解析

报文 1:08 20 20 20 20 20 30 2E 30 36 0D
 
报文 2:08 20 20 20 35 30 30 2E 31 5C 0D
ASCII 解码规则:0x20= 空格,0x0D= 回车\r0x2E= 小数点.

报文 1 拆解

表格
 
HEX082020202020302E30360D
ASCII 退格 BS 空格 空格 空格 空格 空格 0 . 0 6 \r
有效字符串: 0.06\r(前面 5 个空格)
 
数值:0.06

报文 2 拆解

表格
 
HEX082020203530302E315C0D
ASCII 退格 BS 空格 空格 空格 5 0 0 . 1 \ \r
有效字符串: 500.1\\r(前面 3 个空格)
⚠️末尾是反斜杠\,不是数字,大概率是仪表 / 串口输出乱码、校验位或者打印错误;数字部分:500.1

补充说明

  1. 首字节0x08是 BS 退格控制字符,很多串口仪表、称重传感器、数显仪输出会带这个前缀,一般业务解析直接忽略 0x08 即可。
  2. 0x0D是回车结束符,作为一帧结束标志。
  3. 报文 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;
        }
    }
}

 

posted @ 2026-08-27 10:34  txwtech  阅读(8)  评论(0)    收藏  举报