一、GNSS
1、GNSS
GNSS是Global Navigation Satellite System的缩写。中文译名应为全球导航卫星系统。目前,GNSS包含了美国的GPS、俄罗斯的GLONASS、中国的Compass(北斗)、欧盟的 Gali.
2、GPS信号
参考:https://blog.csdn.net/bit_kaki/article/details/81163371
(1)GPS信号结构
C/A码:粗码,提供给民用
P码:精码,军用。
(2)定位原理
卫星不间断地发送自身的星历参数和时间信息,用户接收到这些信息后,经过计算求出接收机的三维位置,三维方向以及运动速度和时间信息。
3、DGPS(差分全球定位系统)
目前 GPS 系统提供的定位精度是优于 10 米,而为得到更高的定位精度,我们通常采用差分 GPS 技术:将一台 GPS 接收机安置在基准站上进行观测。根据基准站已知精密坐标,计算出基准站到卫星的距离改正数,并由基准站实时将这一数据发送出去。用户接收机在进行 GPS 观测的同时,也接收到基准站发出的改正数,并对其定位结果进行改正,从而提高定位精度。
二、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字符。)
(2)GPGSA
当前卫星信息
(3)GPGSV
可见卫星信息,反映GPS可见星的方位角、俯仰角、信噪比等。
格式:
(4) GPRMC
推荐定位信息
格式:
(5)GPVTG
地面速度信息
格式:
(6)GPGLL
定位地理信息
格式:
三、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;
}
}
}
}
}
}