1GPS資料格式

 

NMEA-0183是美國國家海洋電子協會(National Marine Electronics Association)制定的GPS介面協定標準。這種介面協定採用ASCII碼輸出,協議定義了若干代表不同含義的語句,語句格式如表13-1所示。

 

13-1 NMEA-0183語句格式[38]

 

符號(ASCII

定義

HEX

DEX

說明

$

起始位

24

36

語句起始位

  aaccc

地址域

  

 

前兩位為位識別符,後三位為語句名

“,”

域分隔符號

2C

44

域分隔符號

ddd……ddd

資料塊

 

 

發送的資料內容

“*”

校驗和符

2A

42

星號分隔符號,表明後面的兩位數是校驗和

Hh

校驗和

 

 

校驗和

/

終止符

0D,0A

13,10

回車,換行

NMEA0183介面協定定義的主要語句有:GGAGLLGSAGSVMSSRMCVTGZDA等。表13-2介紹這些語句所包含的具體內容。

 

13-2 常見NMEA-0183語句內容[38]

 

語句

語句內容

GGA

UTC時間、緯度值、經度值、定位狀態(無效、單點定位、差分)、觀測的GPS衛星個數、HDOP值、GPS橢球高、天線架設高度、差分數據齡期、差分基準站編號、校驗和

GLL

UTC時間、緯度值、經度值、定位狀態(無效、單點定位、差分)、校驗和

GSA

定位模式(M-手動,強制二維或三維定位;A-自動,自動二維或三維定位)、定位中使用的衛星ID號、PDOP值、HDOP值、VDOP

GSV

視野中的GPS衛星顆數、PRN編號、衛星仰角、距正北的角度(方位角)、信噪比

MSS

信標台的信號強度、信噪比、信標頻率、串列傳輸速率、通道號

RMC

UTC時間、定位狀態(A-可用,V-可能有錯誤)、緯度值、經度值、對地速度、日期等

VTG

對地速度等

ZDA

UTC時間、年、月、日、當地時區、時區的分鐘值等

 

 

 

 

 

1.GPSGlobal Positioning System):全球衛星定位系統
美國的24顆衛星不停地給地面發GPS信號,只要有一台GPS接收設備,就能定位出你所在的位置高度和速度了,它與電子地圖的結合就是通常所說的GPS功能

 

三、gps資料格式

 

1.從串列埠中讀出的是文本資料,每次讀出一行,一般情況下,一秒種能收到多行資料

 

2.有效資料以$GP開頭,分為$GPGGA$GPGSA$GPGSV$GPRMC…

 

 

nmea資料如下:
$GPGGA,121252.000,3937.3032,N,11611.6046,E,1,05,2.0,45.9,M,-5.7,M,,0000*77
$GPRMC,121252.000,A,3958.3032,N,11629.6046,E,15.15,359.95,070306,,,A*54
$GPVTG,359.95,T,,M,15.15,N,28.0,K,A*04
$GPGGA,121253.000,3937.3090,N,11611.6057,E,1,06,1.2,44.6,M,-5.7,M,,0000*72
$GPGSA,A,3,14,15,05,22,18,26,,,,,,,2.1,1.2,1.7*3D
$GPGSV,3,3,10,29,07,074,,30,07,163,28*7D

 

注:NMEA0183格式以“$”開始,主要語句有GPGGA,GPRMC,GPGSA,GPGSV,GPVTGGPZDA

 

 

 

2.1 GPS DOP and Active SatellitesGSA)當前衛星資訊

 

$GPGSA,<1>,<2>,<3>,<4>,,,,,<12>,<13>,<14>, <15>,<16>,<17>,<18>

 

<1>模式 :M = 手動, A = 自動。
<2>
定位型式 1 = 未定位, 2 = 二維定位, 3 = 三維定位。
<3>
<14>PRN 數字:01 32 表天空使用中的衛星編號,最多可接收12顆衛星資訊

 

      (上面藍色處,總共有12)
<15> PDOP
位置精度因數(0.5~99.9
<16> HDOP
水準精度因數(0.5~99.9
<17> VDOP
垂直精度因數(0.5~99.9
<18> Checksum.(
檢查位).

 


2.2
GPS Satellites in ViewGSV)可見衛星資訊
$GPGSV, <1>,<2>,<3>,<4>,<5>,<6>,<7>,?<4>,<5>,<6>,<7>,<8>

 

<1> GSV語句的總數
<2>
本句GSV的編號
<3>
可見衛星的總數,00 12
<4>
衛星編號, 01 32
<5>
衛星仰角, 00 90 度。
<6>
衛星方位角, 000 359 度。實際值。
<7>
訊號雜訊比(C/No), 00 99 dB;無表未接收到訊號。
<8>Checksum.(
檢查位).

 

<4>,<5>,<6>,<7>項個別衛星會重複出現,每行最多有四顆衛星。其餘衛星資訊會于次一行出現,若未使用,這些欄位會空白。

 

 

 

2.3Global Positioning System Fix DataGGAGPS定位資訊

 

$GPGGA,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,M,<10>,M,<11>,<12>*hh

 

<1> UTC時間,hhmmss(時分秒)格式
<2>
緯度ddmm.mmmm(度分)格式(前面的0也將被傳輸)
<3>
緯度半球N(北半球)或S(南半球)
<4>
經度dddmm.mmmm(度分)格式(前面的0也將被傳輸)
<5>
經度半球E(東經)或W(西經)
<6> GPS
狀態:0=未定位,1=非差分定位,2=差分定位,6=正在估算
<7>
正在使用解算位置的衛星數量(00~12)(前面的0也將被傳輸)
<8> HDOP
水準精度因數(0.5~99.9
<9>
海拔高度(-9999.9~99999.9
<10>
地球橢球面相對大地水準面的高度
<11>
差分時間(從最近一次接收到差分信號開始的秒數,如果不是差分定位將為空)
<12>
差分站ID0000~1023(前面的0也將被傳輸,如果不是差分定位將為空)

 


2.4
Recommended Minimum Specific GPS/TRANSIT DataRMC)推薦定位資訊

 

$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh

 

<1> UTC時間,hhmmss(時分秒)格式
<2>
定位狀態,A=有效定位,V=無效定位
<3>
緯度ddmm.mmmm(度分)格式(前面的0也將被傳輸)
<4>
緯度半球N(北半球)或S(南半球)
<5>
經度dddmm.mmmm(度分)格式(前面的0也將被傳輸)
<6>
經度半球E(東經)或W(西經)
<7>
地面速率(000.0~999.9節,前面的0也將被傳輸)
<8>
地面航向(000.0~359.9度,以真北為參考基準,前面的0也將被傳輸)
<9> UTC
日期,ddmmyy(日月年)格式
<10>
磁偏角(000.0~180.0度,前面的0也將被傳輸)
<11>
磁偏角方向,E(東)或W(西)
<12>
模式指示(僅NMEA0183 3.00版本輸出,A=自主定位,D=差分,E=估算,N=資料無效)

 

 

 

2.5 Track Made Good and Ground SpeedVTG)地面速度資訊
$GPVTG,<1>,T,<2>,M,<3>,N,<4>,K,<5>*hh
<1>
以真北為參考基準的地面航向(000~359度,前面的0也將被傳輸)
<2>
以磁北為參考基準的地面航向(000~359度,前面的0也將被傳輸)
<3>
地面速率(000.0~999.9節,前面的0也將被傳輸)
<4>
地面速率(0000.0~1851.8公里/小時,前面的0也將被傳輸)
<5>
模式指示(僅NMEA0183 3.00版本輸出,A=自主定位,D=差分,E=估算,N=資料無效)

 

 

 

2.6GPZDA日期和時間

 

$GPZDA,<1>,<2>, <3> , <4> , <5> , <6> *CC

 

<1> UTC時間,hhmmss(時分秒)格式
<2>

<3>

<4>

<5>
本地時區小時便宜量
<6>
本地時區分鐘便宜量

 

 

 

3.0 程式設計

 

 

利用strstr函數和sscanf函數解析GPS資料。

 

GPS輸出的資料格式如下:
$GPGGA,121252.000,3937.3032,N,11611.6046,E,1,05,2.0,45.9,M,-5.7,M,,0000*77
$GPRMC,121252.000,A,3958.3032,N,11629.6046,E,15.15,359.95,070306,,,A*54
$GPVTG,359.95,T,,M,15.15,N,28.0,K,A*04
$GPGGA,121253.000,3937.3090,N,11611.6057,E,1,06,1.2,44.6,M,-5.7,M,,0000*72
$GPGSA,A,3,14,15,05,22,18,26,,,,,,,2.1,1.2,1.7*3D
$GPGSV,3,1,10,18,84,067,23,09,67,067,27,22,49,312,28,15,47,231,30*70
$GPGSV,3,2,10,21,32,199,23,14,25,272,24,05,21,140,32,26,14,070,20*7E
$GPGSV,3,3,10,29,07,074,,30,07,163,28*7D

 

可以看到,GPS模組發送過來的原始資料有很多,但是通常我們只需要其中的一部分資訊就夠用了,比如對於導航的功能,我們只需要以$GPRMC開頭,以換行符結束的一行資訊就夠了。即:
$GPRMC,121252.000,A,3958.3032,N,11629.6046,E,15.15,359.95,070306,,,A*54

 

因此我們需要做的就是從讀取的資料中截取以$GPRMC開頭的一行資訊,然後從中解析出經緯度、日期時間等有效資訊即可。

 

假設從串口讀取的資料存放在一個字串指標char *raw_buf指向的記憶體單元裏,首先我們通過ANSI C提供的strstr()函數找到以$GPRMC開頭以換行符’\n’結束的字串:
/* find "$GPRMC" from raw_buf */
if ((wellhandled_string = strstr(raw_buf, “$GPRMC”)) != NULL)
{
        for (i=0; i         {
                if (wellhandled_string[i] == '\n')
                {
                        wellhandled_string[i] = '\0'; //replace ‘\n’ with null
                }
        }
}
strstr()
函數的原型是這樣聲明的:
char *strstr(const char *haystack, const char *needle);

 

strstr()函數可以在字串haystack中搜索字串needle第一次出現的 位置,並且返回指向字串needle首位址的指標,如果沒有搜索到則返回NULL。因此上面的代碼為我們在讀取的原始資料raw_buf裏搜 索$GPRMC第一次出現的位置,並將返回的指針賦給wellhandled_string,這樣如果搜索成功,則wellhandled_string 就會指向以$GPRMC開始的字串,接下來通過一個for迴圈找到換行符’\n’,將其替換為’\0’,即字串結束符。這樣就得到了一個指向有效資料 的字串指標wellhandled_string

 

然後要做的工作就是從wellhandled_string中提取出經緯度、日期時間等資訊。這個工作就可以交給強大的sscanf函數來實現。sscanf函數的原型如下:
int sscanf(const char *str, const char *format, ...);

 

我們都比較熟悉scanf這個函數,scanf可以從標準輸入流讀取與指定格式相符的數 據。sscanf則是從const char *str中讀取。它的強大之處在於可以方便地從字串中取出整數、浮點數和字串等各種類型的資料,而且它還具有類似於正則運算式的匹配功 能,sscanf默認是以空格分隔字串的,如果不是以空格來分割的話,就可以使用%[ ]來指定分割的條件。如%[a-z]表示讀取az的所有字元,%[^a-z]表示過濾a-z之間的所有字元,即只要遇到az之間的任意字元,轉換立刻 停止。比如:
sscanf(“abcdefABCDEF”, “%[^A-Z]”, str);
printf(“%s\n”, str);
result is: abcdef
%[^A-Z]
這樣的匹配格式為我們取遇到大寫字母為止的字串。利用這種匹配方式,我們就可以靈活的操作字串,得到我們想要的結果。

 

現在我們需要從下面的字串中提取有效資訊:
$GPRMC,121252.000,A,3958.3032,N,11629.6046,E,15.15,359.95,070306,,,A*54

 

GPRMC每個欄位的含義如下:
$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh
<1> UTC
時間,hhmmss(時分秒)格式
<2>
定位狀態,A=有效定位,V=無效定位
<3>
緯度ddmm.mmmm(度分)格式(前面的0也將被傳輸)
<4>
緯度半球N(北半球)或S(南半球)
<5>
經度dddmm.mmmm(度分)格式(前面的0也將被傳輸)
<6>
經度半球E(東經)或W(西經)
<7>
地面速率(000.0~999.9節,前面的0也將被傳輸)
<8>
地面航向(000.0~359.9度,以真北為參考基準,前面的0也將被傳輸)
<9> UTC
日期,ddmmyy(日月年)格式
<10>
磁偏角(000.0~180.0度,前面的0也將被傳輸)
<11>
磁偏角方向,E(東)或W(西)
<12>
模式指示(僅NMEA0183 3.00版本輸出,A=自主定位,D=差分,E=估算,N=資料無效)

 

我們提取1~9九條資訊。用一個結構體存放這些資訊:
typedef struct gps_info
{
        char utc_time[BUF_SIZE];
        char status;
        float latitude_value;
        char latitude;
        float longtitude_value;
        char longtitude;
        float speed;
        float azimuth_angle;
        char utc_data[BUF_SIZE];
}GPS_INFO;

 

因為每一個欄位之間都是以逗號間隔開的,所以我們可以利用%[^,]來分割字串,這樣用sscanf函數就可以實現對有效資訊的提取:
sscanf(wellhandled_string,"$GPRMC,%[^,],%c,%f,%c,%f,%c,%f,%f,%[^,]",
            rmc_info->utc_time,\
            &(rmc_info->status),&(rmc_info->latitude_value),&(rmc_info->latitude),\
            &(rmc_info->longtitude_value),&(rmc_info->longtitude),&(rmc_info->speed),\
            &(rmc_info->azimuth_angle),\
            rmc_info->utc_data );
這個函數執行後,列印出的保存在struct gps_info結構體裏的資訊如下所示:
utc_time: 024813.640
status: A
latitude: N latitude value: 3158.460693
longtitude: E longtitude value: 11848.374023
speed: 10.050000
azimuth_angle: 324.269989
utc_data: 150706

 

可見,利用好sscanf函數,可以讓我們可以很高效的處理字串。

 

sscanf 教學請看

 

 http://ccckmit.wikidot.com/cp:sscanf

 

 

 

參考資料

http://blog.csdn.net/xmxqiyan/article/details/9134025

http://www.embedu.org/Column/Column196.htm

 

http://blog.csdn.net/baishengjie/article/details/5294321

 

 

 

這裡有詳細的gps命令解釋跟各家gps廠命令範例

 

http://www.gpsinformation.org/dale/nmea.htm

 

gps 模擬器..可以模擬gps裝置 由虛擬串列埠 或 真實串列埠 輸出 pgs 語句作測試

 

http://bbs.godeyes.cn/showtopic-339704.aspx

 

 

arrow
arrow
    文章標籤
    GPS
    全站熱搜

    立你斯 發表在 痞客邦 留言(0) 人氣()