zoukankan      html  css  js  c++  java
  • 从串口获得并分析GPS数据

    目前GPS(全球定位系统)定位应用市场日趋成熟,正在进入应用的高速发展时期。看到论坛里不断有人提问关于GPS的问题。现将个人对GPS的了解写出来跟大家一块探讨。
    1、 GPS应用简介
    近年来GPS系统,已经在大地测绘、海上渔用、车辆定位监控、建筑、农业等各个领域得到广泛应用。从九十年代我国引进GPS定位技术开始,经过十多年的市场培育,GPS定位应用进入了发展的最好时机,未来十年基于GPS的应用将会改变我们的生活和工作方式。
    目前市场上的大部分GPS接受模块都是通过RS232串口与MCU进行数据传输的。这些数据包括经度、纬度、海拔高度、时间、卫星使用情况等基本信息。开发人员再依据这些基本数据,进行数据处理来完成整套的定位系统软件。
    2、 数据格式
    在进行数据接受编程之前,先介绍一下该模块的数据格式。它支持NMEA-0183输出格式。信息如下:
    GGA位置测定系统定位资料(Global Positioning System Fix Data)
        GSV 导航卫星资料(GNSS Satellites in View)
        RMC导航卫星特定精简资料(Recommended Minimum Specific GNSS Data)
        VTG 方向及速度等相关资料(Course Over Ground and Ground Speed)
        由于文章篇幅问题,笔者在这里只以接收GGA数据为例,格式如下:
        $GPGGA,hhmmss,dddmm.mmmm,a,dddmm.mmmm,a,x,xx,x.x,x.x,M,,M,x.x,xxxx*CS
        例:$GPGGA,033744,2446.5241,N,12100.1536,E,1,10,0.8,133.4,M,,,,*1F
    说明见表:

    区域

    名称

    单位

    说明

    1

    信息ID

    $GPGGA

     

    GGA协议开始

    2

    UTC时间

    033744

     

    hhmmss

    3

    纬度

    2446.5241

     

    dddmm.mmmm

    4

    /北半球指示

    N

     

    N=north S=south

    5

    经度

    12100.1536

     

    dddmm.mmmm

    6

    /西半球指示

    E

     

    E=east W=west

    7

    定位指示

    1

     

    0 =未定位

    1=定位SPS模式

    2=定位DGPS, SPS模式

    8

    应位卫星数

    10

     

    00-12

    9

    HDOP

    0.8

     

    10

    海拔高度

    133.4

     

    11

    海拔高度单位

    M

     

    12

    WGS84水准面划分

     

     

     

    13

    WGS-84水准面划分单位

     

     

     

    14

    累计GPS数据微分

     

     

     

    15

    参考工作站ID

     

     

     

    16

    校验位

    *1F

     

     

    上面例子中,我们可读出位置信息:北纬24度46.5241分,西经121度00.1536分
                                    格林威治时间:3点37分44秒

    3   部分程序代码(c++)

    1. //初始化串口
    2. //入口:strComm(串口名)
    3. //返回:TRUE(成功);FALSE(失败)
    4. BOOL CGPSDlg::InitComm(CString strComm)
    5. {
    6.     int i;
    7.     DCB dcb;
    8.     COMMTIMEOUTS TimeOuts;
    9.     for (i=0; i<3; i++)                                         //串口最多初始化3次
    10.     {
    11.         m_hComm = CreateFile(strComm, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    12.         if (m_hComm != INVALID_HANDLE_VALUE)
    13.             break;
    14.     }
    15.     if (i == 3)                                                 //串口初始化失败
    16.     {
    17.         AfxMessageBox("串口初始化失败...");
    18.         return FALSE;
    19.     }
    20.     
    21.     SetupComm(m_hComm, MAXLENGTH, MAXLENGTH);                   //设置发送接收缓冲区大小
    22.     
    23.     TimeOuts.ReadIntervalTimeout = 0;                           //设定5个超时参数
    24.     TimeOuts.ReadTotalTimeoutMultiplier = 0;
    25.     TimeOuts.ReadTotalTimeoutConstant = 500;
    26.     TimeOuts.WriteTotalTimeoutMultiplier = 0;
    27.     TimeOuts.WriteTotalTimeoutConstant = 500;
    28.     SetCommTimeouts(m_hComm, &TimeOuts);                        //设置超时参数
    29.     
    30.     GetCommState(m_hComm, &dcb);                                //获得通信状态
    31.     dcb.fAbortOnError = FALSE;                                  //有错误不停止
    32.     dcb.BaudRate = CBR_4800;                                    //波特率4800
    33.     dcb.ByteSize = 8;                                           //8位
    34.     dcb.Parity = NOPARITY;                                      //奇校验
    35.     dcb.StopBits = ONESTOPBIT;                                  //1位停止位
    36.     SetCommState(m_hComm, &dcb);                                //设置通信状态
    37.     PurgeComm(m_hComm, PURGE_TXCLEAR|PURGE_RXCLEAR);            //清空发送和接收缓冲区    
    38.     
    39.     return TRUE;
    40. }
    41. //获得GPS参数
    42. //注意:从GPS接收到的字符串已经在m_strRecv中,由于是定时接收,所以在这个字符串的头和尾都可能存在
    43. //     不完整的NMEA输出字符串,在处理时要特别注意
    44. //返回:TRUE(格式正确);FALSE(格式错误)
    45. BOOL CGPSDlg::GetGPSParam()
    46. {
    47.     int i,j;
    48.     CString str,strNEMA;
    49.         
    50.     //先判断是否接收到数据
    51.     if (m_strRecv.IsEmpty())
    52.         return FALSE;
    53.     //若字符串不是以'$'开头的,必须删掉这部分不完整的
    54.     if (m_strRecv[0] != '$')
    55.     {
    56.         i = m_strRecv.Find('/n', 0);
    57.         if (i == -1)
    58.             return FALSE;                                       //尾部未接收完整,必须等接收完后才能删除
    59.         m_strRecv.Delete(0, i+1);                               //尾部已接收完整(尾部为/r/n结束),删除不完整的部分
    60.     }
    61.     
    62.     //截取完整的NMEA-0183输出语句(m_strRecv中可能有多条语句,每条间以/r/n分隔)
    63.     for (;;)
    64.     {
    65.         i = m_strRecv.Find('/n', 0);
    66.         if (i == -1)
    67.             break;                                              //所有的完整输出语句都已经处理完毕,退出循环
    68.         
    69.         //截取完整的NMEA-0183输出语句
    70.         strNEMA = m_strRecv.Left(i+1);                          
    71.         m_strRecv.Delete(0, i+1);
    72.         //下面对各种输出语句进行分别处理
    73.         if (strNEMA.Find("$GPRMC",0) == 0)
    74.         {
    75.             //该输出语句中的各项以','分隔
    76.             for (i=j=0; strNEMA[i]!='/r'; i++)                  //j为逗号的计数器
    77.             {
    78.                 if (strNEMA[i] == ',')
    79.                 {
    80.                     j++;
    81.                     str = "";
    82.                     for (i++; strNEMA[i]!=','&&strNEMA[i]!='/r'; i++)
    83.                         str += strNEMA[i];                      //str为某项的值
    84.                     i--;
    85.                     
    86.                     //对各项数据分别处理
    87.                     switch (j)
    88.                     {
    89.                     case 1:                                     //时间(UTC)                   
    90.                         m_strTime = str.Left(6);
    91.                         m_strTime.Insert(2, ':');
    92.                         m_strTime.Insert(5, ':');
    93.                         break;
    94.                     case 2:                                     //状态(A-数据有效;V-数据无效,还未定位)
    95.                         if (str == "A")
    96.                             m_strStatus = "有效数据";
    97.                         else if(str == "V")
    98.                             m_strStatus = "正在定位...";
    99.                         else
    100.                             m_strStatus = "非法数据格式";
    101.                         break;
    102.                     case 3:                                     //纬度(ddmm.mmmm)
    103.                         str.Insert(2, "度");
    104.                         str += "分";
    105.                         m_strLatitude = str;
    106.                         break;
    107.                     case 4:                                     //纬度指示(N-北纬;S-南纬)
    108.                         if (str == "N")
    109.                             m_strLatitude.Insert(0, "北纬");
    110.                         else
    111.                             m_strLatitude.Insert(0, "南纬");
    112.                         break;
    113.                     case 5:                                     //经度(dddmm.mmmm)
    114.                         str.Insert(3, "度");
    115.                         str += "分";
    116.                         m_strLongitude = str;
    117.                         break;
    118.                     case 6:                                     //经度指示(E-东经;W-西经)
    119.                         if (str == "E")
    120.                             m_strLongitude.Insert(0, "东经");
    121.                         else
    122.                             m_strLongitude.Insert(0, "西经");
    123.                         break;
    124.                     case 7:                                     //速度(单位:节)
    125.                         m_strSpeed = str;
    126.                         break;
    127.                     case 8:                                     //航向(单位:度)
    128.                         m_strCourse = str;
    129.                         break;
    130.                     case 9:                                     //日期(UTC)
    131.                         m_strDate = "";
    132.                         m_strDate += "20";
    133.                         m_strDate += str[4];
    134.                         m_strDate += str[5];
    135.                         m_strDate += "-";
    136.                         m_strDate += str[2];
    137.                         m_strDate += str[3];
    138.                         m_strDate += "-";
    139.                         m_strDate += str[0];
    140.                         m_strDate += str[1];
    141.                         break;
    142.                     default:
    143.                         break;
    144.                     }
    145.                 }
    146.             }
    147.         }
    148.         else if (strNEMA.Find("$GPGGA",0) == 0)
    149.         {
    150.         
    151.         }
    152.         else if (strNEMA.Find("$GPGSA",0) == 0)
    153.         {
    154.         
    155.         }
    156.         else if (strNEMA.Find("$GPGSV",0) == 0)
    157.         {
    158.         
    159.         }
    160.         else if (strNEMA.Find("$GPGLL",0) == 0)
    161.         {
    162.         
    163.         }
    164.         else if (strNEMA.Find("$GPVTG",0) == 0)
    165.         {
    166.         
    167.         }
    168.         else
    169.             return FALSE;                                       //格式错误
    170.     }
    171.     return TRUE;
    172. }
  • 相关阅读:
    NHibernate 过滤器(第十五篇)
    NHibernate 存储过程 第十四篇
    NHibernate 操作视图 第十三篇
    NHibernate Linq查询 扩展增强 (第九篇)
    NHibernate 之数据操作 (第五篇)
    NHibernate之一级缓存(第十篇)
    jQueryEasyUI
    linux的systemctl 命令用法 转
    linux dig命令 转
    OPTAUTH 两步验证详解
  • 原文地址:https://www.cnblogs.com/cpcpc/p/2123120.html
Copyright © 2011-2022 走看看