一、遇到的问题

我们在使用qt的时候想读取串口里的数据,一般都会使用这样的方式。

 QByteArray rxbuffer;
 rxbuffer.append(serial.readALL());

但是我们串口助手一次是8个比特位,一次性读取的数据会不全。你读取到的数据可能是这样的。

作为一个不完整的数据去后续解析工作,会导致解析不出来正常的数据,因为解析的数据不是正常的起始位,校验位,截止位,我们把这种数据称为无效数据。

二、解决方法

我想到了一种解决方法,并非传统意义上的通过延时函数的方法去解决数据收发不完整的情况。而是定义一个静态的数组去存储不完整的数据,对每一次不完整的数据进行拼接,直到出现起始位和结束位都满足条件的时候,进入解析。我这里的起始位是“$”开头,“\r\n”结尾。

GPSInfo gpsInfo;
    QByteArray rxbuffer;
    static QByteArray incompleteData;
    incompleteData.append(serial1.readAll());
    rxbuffer.append(incompleteData);
    incompleteData.clear();
//    qDebug() << "rxbuffer" << rxbuffer << endl;

    int endPos = rxbuffer.indexOf("\r\n");
    while (endPos != -1) {
        QByteArray sentence = rxbuffer.left(endPos); // 不包括结束标志
        rxbuffer.remove(0, endPos + 2); // 移除已经处理的数据,包括结束标志
        endPos = rxbuffer.indexOf("\r\n");

        if (sentence.startsWith("$")) {
  //          qDebug()<<"SENTENCE"<<sentence;

            switch (minmea_sentence_id(sentence.constData(), false)) {
                case MINMEA_SENTENCE_RMC: {
                   ...
                   ...
                    }
                    break;
                }
                case MINMEA_SENTENCE_HDT: {
                    if (minmea_parse_hdt(&frame_hdt, sentence.constData())) {
                       ...
                       ...
                    }
                    break;
                }
                case MINMEA_SENTENCE_GGA: {
                    if (minmea_parse_gga(&frame, sentence.constData())) {
                        gpsInfo.time = get_double_number(sentence.mid(GetComma(1, sentence)));
                        ...
                        ...
                    }
                    break;
                }
                default:
                    break;
            }
        }
    }

    incompleteData.append(rxbuffer); // 将剩余的不完整数据保存下来

三、运行结果

最后运行结果通过qDebug()打印,只有检测到完整的数据才会进入sentence进行后续解析。如图所示:

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐