c語言 GPS nmealib學習筆記


0.nmealib簡介
 
    nmealib是一個基於C語言的用於nmea協議的開源庫。雖然nmea體積小巧,但是卻具備了不少功能。
 

    分析NMEA語句並把結果保存在合適的C語言結構體中。
 

    除了解析NMEA語句之外,還可以產生NMEA語句。
 

    支持多種NMEA語句,包括GPGGA, GPGSA, GPGSV, GPRMC, GPVTG。
 
    解析算法層次嚴謹。
 

    附加地理學相關功能,可支持導航等數據工作。
 

    更多介紹請參考以下鏈接
 

    http://nmea.sourceforge.net/#downloads
 
1.目錄介紹
 
    nmealib的目錄還是非常清晰的,下面簡單介紹一下。
 

    include\nmealib文件夾中存在nmealib相關的頭文件
 

    src文件夾存放nmealib相關源文件,該文件夾中的內容和include\nmealib文件夾相對應
 
    samples文件夾存放若干例子,一些簡單易懂的例子。
#include <nmea/nmea.h>
#include <string.h>
#include <stdio.h>

int main()
{
    // 被測試的GPS模塊輸出數據,僅有GPRMC格式
    char gps_str[] = "$GPRMC,013257.00,A,3129.51829,N,12022.10562,E,0.093,,270813,,,A*7A\r\n";

    nmeaINFO info;                  // nmea協議解析結果結構體
    nmeaPARSER parser;              // nmea協議解析載體

    nmea_zero_INFO(&info);          // 填入默認的解析結果
    nmea_parser_init(&parser);      // 為解析載體分配內存空間

    // 調用函數完成GPS信息解析,最終結果保留於info數組中
    if( (nmea_parse(&parser, gps_str, (int)strlen(gps_str), &info)) > 0 )
    {
        printf("longitude   %.5f\r\n",info.lon);
        printf("latitude    %.5f\r\n",info.lat);
        printf("speed       %.2f\r\n",info.speed);
    }

    nmea_parser_destroy(&parser);   // 釋放解析載體的內存空間

    return 0;
}

 利用nmealib解析GPS模塊的輸出結果大致可以分為三步,第一步定義和初始化GPS信息結構體和解析載體結構體,第二步調用nmea_parse函數完成解析工作,第三步釋放解析載體所占用的內存空間。如果仔細查看nmea_parser_init部分的代碼,便會發現函數中使用了C標准庫的malloc函數,該函數會在RAM中的heap空間開辟一個空間,這就需要使用完該載體之后立刻釋放,所以nmea_parser_init和nmea_parser_destroy需要成對出現。

   nmeaINFO是一個很關鍵的結構體,該結構體中保存了nmea語句解析的結果。例如lat代表緯度,lon代表精度,speed代表速度。需要注意的是lat和lon的數值格式和百度地圖的格式是有區別的,而速度的單位為KM/H,相對於“節”這個單位,公里每小時要好理解的多。
 
    GPS模塊可以輸出的內容很多,但是最基本的信息可通過GPRMC獲得。GPRMC的具體格式如下內容所示:
$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh
<1> UTC時間,hhmmss.sss(時分秒.毫秒)格式
<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=數據無效)
在不同的情況下測試GPS模塊,可以獲得以下三種不同形式的輸出內容:
1)    $GPRMC,013257.00,A,3129.51829,N,12022.10562,E,0.093,,270813,,,A*7A\r\n
2)    $GPRMC,022649.00,V,,,,,,,020913,,,N*7F\r\n
3)    $GPRMC,,V,,,,,,,,,,N*53\r\n
第一種:GPS定位成功,輸出正確的GPS位置信息和對地速度信息。
第二種:GPS定位異常,只有UTC時間信息,其中V代表定位錯誤。
第三種:GPS定位異常,甚至沒有UTC時間信息,其中V代表定位錯誤。
通過測試,nmealib處理第一種情況沒有任何問題,但是連續處理第二種和第三種情況會產生問題,產生問題的主要原因是動態開辟的空間沒有被釋放。解決該問題需要修改nmealib的源代碼,這種修改是有難度的。
    如果不想修改nmealib源代碼,可以在串口接收GPS輸出內容時直接過濾帶有V的字符串,這種方法簡單有效,同樣可以獲得准確的GPS坐標信息。

3.若干注意點

3.1 重置解析載體緩沖區
    由於nmealib雖然使用C語言,但是相關測試環境均基於PC環境,所以在嵌入式環境下需要對相關參數(宏定義)進行修改。例如context.h文件中,定義了待處理的nmea緩沖區的大小,相關宏定義如下
#define NMEA_DEF_PARSEBUFF  (1024)
#define NMEA_MIN_PARSEBUFF  (256)
   示例代碼的分析中提到,解析載體parser通過動態內存分配的方法開辟空間,該空間位於RAM空間中的heap部分,如果heap部分設置的太小,將會導致MCU進入不可預知的狀態或者直接掉入斷言中。
在編譯器設置中,option->linker,cstack和heap的大小設置如下圖所示,此時heap的大小僅有512個字節,而解析載體卻需要1024個字節,那么分配內存時勢必會產生問題,而工程的編譯卻不會有任何問題。
 

4.總結

    nmealib的使用可以縮短GPS的開發周期,這里只是簡單的舉例了nmealib的基本功能,更多的功能可以查看samples文件夾中的例子,並在實踐中不斷熟悉提高。
    示例工程鏈接:百度網盤
    簡要說明:IAR ARM 6.5 simulator
 
更多


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM