GPS協議解析
一份相對較完整的協議文字,並且編寫了一個相對較完善的 GPS 協議解析程式。
上圖是我所說的測試程式,已經可以獲得定位資料及相關衛星資訊。
NMEA 0183 是美國國家海洋電子協會(National Marine Electronics Association ) 為海用電子裝置制定的標準格式。目前業已成了 GPS 導航裝置統一的 RTCM 標準協議。
序號 |
命令 |
說明 |
最大幀長 |
1 |
$GPGGA |
全球定位資料 |
72 |
2 |
$GPGSA |
衛星PRN 資料 |
65 |
3 |
$GPGSV |
衛星狀態資訊 |
210 |
4 |
$GPRMC |
運輸定位資料 |
70 |
5 |
$GPVTG |
地面速度資訊 |
34 |
6 |
$GPGLL |
大地座標資訊 |
|
7 |
$GPZDA |
UTC 時間和日期 |
注:傳送次序$PZDA 、$GPGGA 、$GPGLL 、$GPVTG 、$GPGSA 、$GPGSV*3 、$GPRMC
協議幀總說明:
該協議採用ASCII
碼,其序列通訊預設引數為:波特率=4800bps
,資料位=8bit
,開始位=1bit
幀格式形如:$aaccc,ddd,ddd,…,ddd*hh<CR><LF>
1 、“$”-- 幀命令起始位
2 、aaccc-- 地址域,前兩位為識別符,後三位為語句名
3 、ddd…ddd— 資料
4 、“* ”— 校驗和字首
5 、hh— 校驗和, $ 與* 之間所有字元程式碼的校驗和(各位元組做異或運算,得到校驗和後,再轉換16 進位制格式的ASCII 字元。)
6 、 <CR><LF>-- 幀結束,回車和換行
其中
$GPRMC
比較重要,下面略加介紹。
1 、$GPRMC( Recommended Minimum Specific GPS/TRANSIT Data)
幀頭 |
UTC 時間 |
狀態 |
緯度 |
北緯/ 南緯 |
經度 |
東經/ 西經 |
速度 |
$GPRMC |
hhmmss.sss |
A/V |
ddmm.mmmm |
N/S |
dddmm.mmmm |
E/W |
節 |
方位角 |
UTC 日期 |
磁偏角 |
磁偏角方向 |
模式 |
校驗 |
回車換行 |
度 |
ddmmyy |
000 - 180 |
E/W |
A/D/E/N |
*hh |
CR+LF |
格 式: $GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh<CR><LF>
$GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A*50
說 明:
欄位 0 :$GPRMC ,語句ID ,表明該語句為Recommended Minimum Specific GPS/TRANSIT Data (RMC )推薦最小定位資訊
欄位 1 :UTC 時間,hhmmss.sss 格式
欄位 2 :狀態,A= 定位,V= 未定位
欄位 3 :緯度ddmm.mmmm ,度分格式(前導位數不足則補0 )
欄位 4 :緯度N (北緯)或S (南緯)
欄位 5 :經度dddmm.mmmm ,度分格式(前導位數不足則補0 )
欄位 6 :經度E (東經)或W (西經)
欄位 7 :速度,節,Knots ( 一節也是 1.852 千米/小時)
欄位 8 :方位角,度( 二維方向指向,相當於二維羅盤)
欄位 9 :UTC 日期,DDMMYY 格式
欄位10 :磁偏角,(000 - 180 )度(前導位數不足則補0 )
欄位11 :磁偏角方向,E= 東,W= 西
欄位12 :模式,A= 自動,D= 差分,E= 估測,N= 資料無效(3.0 協議內容)
欄位13 :校驗值
對應的程式程式碼如下:
- //運輸定位資料
- private bool GPRMC_Parse( string data)
- {
- string [] source = Split(data, "$GPRMC" );
- if (source != null && source.Length >= 12)
- {
- //狀態
- this .AnchorState = source[2];
- //緯度
- if (source[4].Length > 0 && source[3].Length > 2)
- {
- this .Latitude = string .Format( "{0}{1},{2}" , source[4], source[3].Substring(0, 2), source[3].Substring(2));
- }
- else
- {
- this .Latitude = "" ;
- }
- //經度
- if (source[6].Length > 0 && source[5].Length > 3)
- {
- this .Longitude = string .Format( "{0}{1},{2}" , source[6], source[5].Substring(0, 3), source[5].Substring(3));
- }
- else
- {
- this .Longitude = "" ;
- }
- //速度
- if (source[7].Length > 0)
- {
- this .NSpeed = double .Parse(source[7]);
- }
- else
- {
- this .NSpeed = 0;
- }
- //方位
- if (source[8].Length > 0)
- {
- this .Track = double .Parse(source[8]);
- }
- else
- {
- this .Track = 0;
- }
- //磁偏角和方位
- if (source[10].Length > 0 && source[11].Length > 0)
- {
- this .Magnetic = string .Format( "{0} {1}" , source[11], source[10]);
- }
- else
- {
- this .Magnetic = "" ;
- }
- //模式
- if (source.Length >= 13)
- {
- this .WorkMode = source[12];
- }
- //時間
- try
- {
- if (source[9].Length == 6 && source[1].Length >= 6)
- {
- string dtString = string .Format( "{0}-{1}-{2} {3}:{4}:{5}" ,
- source[9].Substring(4),
- source[9].Substring(2, 2),
- source[9].Substring(0, 2),
- source[1].Substring(0, 2),
- source[1].Substring(2, 2),
- source[1].Substring(4));
- this .UTCDateTime = DateTime.Parse(dtString);
- }
- }
- catch { return false ; }
- return true ;
- }
- return false ;
- }