C#接收GNSS NMEA0813协议数据

一、GNSS

1、GNSS

 GNSS是Global Navigation Satellite System的缩写。中文译名应为全球导航卫星系统。目前,GNSS包含了美国的GPS、俄罗斯的GLONASS、中国的Compass(北斗)、欧盟的 Gali.

C#接收GNSS NMEA0813协议数据_第1张图片

 

2、GPS信号

参考:https://blog.csdn.net/bit_kaki/article/details/81163371

(1)GPS信号结构

  • 每个GPS卫星播发一组信号
  • 每组信号包括两个不同频率的载波信号(L1和L2)、两个不同的测距码信号(C/A码调制在L1载波上,P码或Y码同时调制在L1及L2载波上)以及卫星的轨道信息

C/A码:粗码,提供给民用

P码:精码,军用。

C#接收GNSS NMEA0813协议数据_第2张图片

C#接收GNSS NMEA0813协议数据_第3张图片

(2)定位原理

      卫星不间断地发送自身的星历参数和时间信息,用户接收到这些信息后,经过计算求出接收机的三维位置,三维方向以及运动速度和时间信息。

C#接收GNSS NMEA0813协议数据_第4张图片

3、DGPS(差分全球定位系统)

       目前 GPS 系统提供的定位精度是优于 10 米,而为得到更高的定位精度,我们通常采用差分 GPS 技术:将一台 GPS 接收机安置在基准站上进行观测。根据基准站已知精密坐标,计算出基准站到卫星的距离改正数,并由基准站实时将这一数据发送出去。用户接收机在进行 GPS 观测的同时,也接收到基准站发出的改正数,并对其定位结果进行改正,从而提高定位精度。

C#接收GNSS NMEA0813协议数据_第5张图片

二、NMEA0813

1、NMEA0813

 NMEA-0183是美国国家海洋电子协会(National Marine Electronics Association )为海用电子设备制定的标准格式。目前也已形成了GPS/北斗导航设备统一的RTCM(Radio Technical Commission for Maritime services)标准协议。
2、协议格式

参考:https://blog.csdn.net/ddway12/article/details/52983627

NMEA-0183协议采用ASCII码来传递GPS定位信息,我们称之为帧。

(1)GPGGA

GPS定位信息,这是一帧GPS定位的主要数据,也是使用最广的数据。

帧格式如下:$aaccc,ddd,ddd,…,ddd*hh 

    “$”——帧命令起始位
    aaccc——地址域,前两位为识别符,后三位为语句名,常用的语句有GPGGA、GPGSA、GPGSV、GPRMC、GPGLL、GPVTG
    ddd…ddd——数据

     “,”是域分隔符
    “*”——校验和前缀
    hh——校验和(check sum),$与*之间所有字符ASCII码的校验和(各字节做异或运算,得到校验和后,再转换16进制格式的ASCII字符。)
    ——CR(Carriage Return) + LF(Line Feed)帧结束,回车和换行

 

C#接收GNSS NMEA0813协议数据_第6张图片

 

 (2)GPGSA

当前卫星信息

格式:

C#接收GNSS NMEA0813协议数据_第7张图片

 (3)GPGSV

可见卫星信息,反映GPS可见星的方位角、俯仰角、信噪比等。

格式:

C#接收GNSS NMEA0813协议数据_第8张图片

 C#接收GNSS NMEA0813协议数据_第9张图片

(4) GPRMC

推荐定位信息

格式:

C#接收GNSS NMEA0813协议数据_第10张图片

(5)GPVTG

地面速度信息

格式:

C#接收GNSS NMEA0813协议数据_第11张图片

(6)GPGLL

定位地理信息

格式:

C#接收GNSS NMEA0813协议数据_第12张图片

C#接收GNSS NMEA0813协议数据_第13张图片

三、C#解析协议

GNSS设备发送数据帧到计算机,编写计算机软件解析协议,提取有用信息。没有GNSS设备,可以用模拟软件模拟发出定位信息 。

使用NemaStudio 1.27软件模拟GPS信号  下载地址:http://www.onlinedown.net/soft/573835.htm

串口接收的程序省略,只写GPS数据的接收和解析部分

 //第一步:串口接收数据
    int n = portRTK.BytesToRead;  //获取接收缓冲区中的字节数
    byte[] buf = new byte[n];  //缓存串口数组
    portRTK.Read(buf, 0, n);      
// 第二步:数据转换成ASCII码,并分割出有用数据
            if (n > 0)
            {
                string rec_str = Encoding.ASCII.GetString(buf, 0, n);
                rec_txt_proc = rec_txt_proc + rec_str;
            }
            n = 0;
            string[] rec_cmd_array = rec_txt_proc.Split('$');//找到所有的数据帧
            if (rec_cmd_array.Length > 0)
            {
                //循环遍历所有的数据帧
                for (int i = 1; i < rec_cmd_array.Length; i++)
                {
                    string[] check_array = rec_cmd_array[i].Split('*');//分割有用数据
                    if (check_array.Length >1)
                     {
                         string[] rec_0183_cmd_array = check_array[0].Split(',');//继续分割数据
                         byte[] rec_check_bcd = Encoding.ASCII.GetBytes(check_array[1]);//获取校验和和帧尾
//第三步数据校验
                         if (rec_check_bcd.Length == 4)//判断校验和和帧尾是否是4个字节
                         {
                             //数据校验
                                if (rec_check_bcd[0] > 0x40)
                                      rec_check_bcd[0] = Convert.ToByte((rec_check_bcd[0] - 0x41 + 10) & 0xff);
                                else
                                      rec_check_bcd[0] = Convert.ToByte(rec_check_bcd[0] - 0x30);
                                if (rec_check_bcd[1] > 0x40)
                                      rec_check_bcd[1] = Convert.ToByte((rec_check_bcd[1] - 0x41 + 10) & 0xff);
                                else
                                      rec_check_bcd[1] = Convert.ToByte(rec_check_bcd[1] - 0x30);
                                int rec_check = rec_check_bcd[0] * 16 + rec_check_bcd[1];
                                byte[] check_byte = Encoding.ASCII.GetBytes(check_array[0]);
                               int crc = check_byte[0];

                               for (int j = 1; j < check_byte.Length; j++)
                                crc = crc ^ check_byte[j];

                                   if (crc == rec_check)
                                     {
//第四步:提取各种数据帧
                                         switch (rec_0183_cmd_array[0])//判断数据类型并显示
                                         {
                                             case "GPGGA": break;
                                             case "GPGSA": break;
                                             case "GPGSV": break;
                                             case "GPRMC": break;
                                             case "GPVTG": break;
                                             case "GPGLL": break;

                                         }
                                      }
                         }
                       }
                }
            } 

 

你可能感兴趣的:(传感器)