单片机解析 GPS 数据非常简单,只要串口接收到一行字符串,传到解析函数里,再把解析到的字符串经过运算转成我们需要数据。

    硬件平台:XC-GPS 开发板 + XC-STC 单片机开发板

    效果如下:

    首先创建一个 GPS 数据结构体:

    1. typedef data struct{
    2. double latitude; // 经度
    3. double longitude; // 纬度
    4. int latitude_Degree; // 度
    5. int latitude_Cent; // 分
    6. int latitude_Second; // 秒
    7. int longitude_Degree; // 度
    8. int longitude_Cent; // 分
    9. int longitude_Second; // 秒
    10. float speed; // 速度
    11. float direction; // 航向
    12. float height; // 海拔高度
    13. int satellite;
    14. U8 NS;
    15. U8 EW;
    16. DATE_TIME D;
    17. }GPS_INFO;

    时间结构体:

    1. typedef struct{
    2. int year;
    3. int month;
    4. int day;
    5. int hour;
    6. int minute;
    7. int second;
    8. }DATE_TIME;

    核心算法就是解析 GPRMC 数据,得到经纬度,日期时间,速度,航向:

    1. int GPS_RMC_Parse(char line, GPS_INFO GPS)
    2. {
    3. U8 ch, status, tmp;
    4. float lati_cent_tmp, lati_second_tmp;
    5. float long_cent_tmp, long_second_tmp;
    6. float speed_tmp;
    7. char *buf \= line;
    8. ch \= buf[5];
    9. status \= buf[GetComma(2, buf)];
    10. if (ch \=\= ‘C’) // 如果第五个字符是 C,($GPRMC)
    11. {
    12. if (status \=\= ‘A’) // 如果数据有效,则分析
    13. {
    14. GPS->NS \= buf[GetComma(4, buf)];
    15. GPS->EW \= buf[GetComma(6, buf)];
    16. GPS->latitude \= Get_Double_Number(&buf[GetComma(3, buf)]);
    17. GPS->longitude \= Get_Double_Number(&buf[GetComma(5, buf)]);
    18. GPS->latitude_Degree \= (int)GPS->latitude / 100; // 分离纬度
    19. lati_cent_tmp \= (GPS->latitude - GPS->latitude_Degree * 100);
    20. GPS->latitude_Cent \= (int)lati_cent_tmp;
    21. lati_second_tmp \= (lati_cent_tmp - GPS->latitude_Cent) * 60;
    22. GPS->latitude_Second \= (int)lati_second_tmp;
    23. GPS->longitude_Degree \= (int)GPS->longitude / 100; // 分离经度
    24. long_cent_tmp \= (GPS->longitude - GPS->longitude_Degree * 100);
    25. GPS->longitude_Cent \= (int)long_cent_tmp;
    26. long_second_tmp \= (long_cent_tmp - GPS->longitude_Cent) * 60;
    27. GPS->longitude_Second \= (int)long_second_tmp;
    28. speed_tmp \= Get_Float_Number(&buf[GetComma(7, buf)]); // 速度 (单位:海里 / 时)
    29. GPS->speed \= speed_tmp * 1.85; //1 海里 \=1.85 公里
    30. GPS->direction \= Get_Float_Number(&buf[GetComma(8, buf)]); // 角度
    31. GPS->D.hour \= (buf[7] - ‘0’) * 10 + (buf[8] - ‘0’); // 时间
    32. GPS->D.minute \= (buf[9] - ‘0’) * 10 + (buf[10] - ‘0’);
    33. GPS->D.second \= (buf[11] - ‘0’) * 10 + (buf[12] - ‘0’);
    34. tmp \= GetComma(9, buf);
    35. GPS->D.day \= (buf[tmp + 0] - ‘0’) * 10 + (buf[tmp + 1] - ‘0’); // 日期
    36. GPS->D.month \= (buf[tmp + 2] - ‘0’) * 10 + (buf[tmp + 3] - ‘0’);
    37. GPS->D.year \= (buf[tmp + 4] - ‘0’) * 10 + (buf[tmp + 5] - ‘0’) + 2000;
    38. UTC2BTC(&GPS->D);
    39. return 1;
    40. }
    41. }
    42. return 0;
    43. }

    line 是串口接收的一行数据 buf

    GetComma 函数作用是一行数据中第几个逗号后面那个字符在这行数据中的位置

    Get_Double_Number 函数作用是把给定字符串第一个逗号之前的字符转化成双精度型,在这里就是把代表经度和纬度的字符串转换成数字,同样的函数还有 Get_Float_Number

    UTC2BTC 函数是将世界时间转换成北京时间(相差 8 小时)

    在 LCD 显示程序中把 GPS_INFO 结构体的已经被赋值的变量显示到屏上相应的位置即可

    还有一个 GPGGA 信息段可以提供海拔高度和卫星数量信息

    1. int GPS_GGA_Parse(char line, GPS_INFO GPS)
    2. {
    3. U8 ch, status;
    4. char *buf \= line;
    5. ch \= buf[4];
    6. status \= buf[GetComma(2, buf)];
    7. if (ch \=\= ‘G’) //$GPGGA
    8. {
    9. if (status !\= ‘,’)
    10. {
    11. GPS->height \= Get_Float_Number(&buf[GetComma(9, buf)]);
    12. GPS->satellite \= Get_Int_Number(&buf[GetComma(7, buf)]);
    13. return 1;
    14. }
    15. }
    16. return 0;
    17. }

    阅读 (21612) | 评论 (5) | 转发 (4) |
    http://blog.chinaunix.net/uid-22030783-id-461988.html