NMEA协议解析和CRC校验

一、NMEA0183协议
NMEA0183协议协议解析,详细 NMEA协议标准参考链接: https://pan.baidu.com/s/1AagpjzvIkA-eJDj6t-efnA 提取码: c8f2 复制这段内容后打开百度网盘手机App,操作更方便哦

1、NMEA基本框架·
以第1行数据为例:$GNGGA,081729.804,,,,,0,0,,,M,,M,,*5F<CR><LF>

$是起始符,所有的语句都是以$开始

<CR><LF>是回车换行符为结束序列,所有的语句都是以<CR><LF>结束

<CR>:ASCII 13, \r

<LF>:ASCII 10, \n

*5F,*后面跟的是校验和,其中5F代表校验和,对$和*之间的数据(不包括这两个字符)按字节进行异或运算(二进制)的结果,以十六进制表示。

2、常用语句

1)GNGGA

以第1行数据为例:$GNGGA,081729.804,,,,,0,0,,,M,,M,,*5F<CR><LF>。GNGGA的GN是发送器的标识符,表示是GNSS,定义如下:

 

 

GGA:输出接收机时间、位置及定位相关的数据。

格式:$--GGA,UTCtime,Lat,uLat,Lon,uLon,FS,numSv,HDOP,Msl,uMsl,Sep,uSep,DiffAge,DiffSta*CS<CR><LF>

 

081729.804表示UTC时间8h:17min:29.804s,UTC时间格式是hhmmss.sss,北京时间需要在此基础上+8h。

因为这一包数据是未定位数据,所以有,,,,,少了四个数据对应经纬度信息。

,0,0,第一个0表示当前定位不可用或无效,第2个0表示用于定位的卫星数量为0。

,M,,M,这2个M都是固定字符,高度的单位米。

2)GNGLL

$GNGLL,,,,,081729.804,V,N*6D<CR><LF>

同上因为未定位,无经纬度信息,多以有5个,

081729.804表示UTC时间同上。

VN均表示数据无效。

6D表示BCC校验和。

3)GNGSA

$GNGSA,A,1,,,,,,,,,,,,,,,,1*1D<CR><LF>

A表示自动切换

1表示定位无效

4)GPGSV

$GPGSV,4,1,13,10,69,178,35,196,64,139,25,194,61,094,,32,53,007,35,1*65<CR><LF>

$GPGSV,4,2,13,25,51,063,28,31,48,279,27,22,38,330,,23,37,158,,1*69<CR><LF>

$GPGSV,4,3,13,26,21,204,,12,19,044,,195,12,154,,29,07,124,,1*5E<CR><LF>

$GPGSV,4,4,13,21,05,290,,1*5B<CR><LF>

4表示该条GSV语句中有4个参数组。

1表示该条是第1句,后面有$GPGSV,4,2、$GPGSV,4,3、$GPGSV,4,4。

因为总共卫星数为13>4,所以需要13/4=3余1,也就是需要四个语句。以第一个语句为例,包含了四颗卫星的信息,分别是10,69,178,35、196,64,139,25、194,61,094,,、32,53,007,35,其中第3组信息中载噪比为空,表示没有跟踪到编号194的卫星。

4)GNRMC

$GNRMC,081729.804,V,,,,,,,111022,,,N,V*21<CR><LF>

081729.804表示UTC时间同上。

V表示数据无效。

111022表示22年10月11日,数据格式为ddmmyy(先日后月再年)

N所在位是定位模式标志,表示数据无效。

6)GNVTG

$GNVTG,,T,,M,,N,,K,N*32<CR><LF>

对应解析数据即可。T、M、N、K均是固定字符。

7)GNZDA

$GNZDA,081729.804,11,10,2022,,*42<CR><LF>

081729.804表示UTC时间同上。

11,10,2022表示日/月/年。

二、CRC校验代码

    @Test
    public void validate() {
        String str = "$MSTHS,124.0,*78";
        byte[] response = StrUtil.bytes(str);
        List<Character> characters = new ArrayList<>();
        List<String> modelList = new ArrayList<>();
        for (int i = 0; i < response.length; i++) {
            char a = (char) response[i];
            characters.add(a);
        }
        handleN(characters, modelList, '$');
    }

    private void handleN(List<Character> characters, List<String> modelList, char prefix) {
        int size = characters.size();
        char result = 0;

        for (int i = 0; i < size; i++) {
            char a = characters.get(i);
            if (a != prefix) {
                if (a == '*') {
                    System.out.println("判断result的16进制是否与16进制的78相等即可~~");
                    break;
                } else {
                    log.info("a = {} - {}",a,Integer.toBinaryString(a));
                    result ^= a;
                    log.info("b = {} - {}",result,Integer.toBinaryString(result));
                }
            }
        }
    }

 

posted @ 2023-01-06 17:34  方大帝的博客  阅读(1700)  评论(0编辑  收藏  举报