GPS数据读取与处理

转自:http://www.cnblogs.com/emouse/archive/2013/05/29/3105745.html

GPS模块简介

SiRF芯片在2004年发布的最新的第三代芯片SiRFstar III(GSW 3.0/3.1),使得民用GPS芯片在性能方面登上了一个顶峰,灵敏度比以前的产品大为提升。这一芯片通过采用20万次/频率的相关器提高了灵敏度,冷开机/暖开机/热开机的时间分别达到42s/38s/8s,可以同时追踪20个卫星信道。是目前市场上应用最为广泛,同时性价比也非常高的一款芯片,因此在本设计中同样采用以此芯片为核心的GPS模块。

GPS模块的数据格式

对GPS模块的数据处理本质上还是串口通信程序设计,只是GPS模块的输出遵循固定的格式,通过字符串检索查找即可从模块发送的数据中找出需要的数据,常用的GPS模块大多采用NMEA-0183 协议。NMEA-0183 是美国国家海洋电子协会(National Marine Electronics Association)所指定的标准规格,这一标准制订所有航海电子仪器间的通讯标准,其中包含传输资料的格式以及传输资料的通讯协议。

以下是一组正常的GPS 数据

$GPGGA,082006.000,3852.9276,N,11527.4283,E,1,08,1.0,20.6,M,,,,0000*35

$GPRMC,082006.000,A,3852.9276,N,11527.4283,E,0.00,0.0,261009,,*38

$GPVTG,0.0,T,,M,0.00,N,0.0,K*50

下面分别对每组数据的含义进行分析。

GPS 固定数据输出语句($GPGGA),这是一帧GPS 定位的主要数据,也是使用最广的数据。为了便于理解,下面举例说明$GPGGA语句各部分的含义。

例:$GPGGA,082006.000,3852.9276,N,11527.4283,E,1,08,1.0,20.6,M,,,,0000*35

其标准格式为:

$GPGGA,(1),(2),(3),(4),(5),(6),(7),(8),(9),M,(10),M,(11),(12)*hh(CR)(LF)

各部分所对应的含义为:

(1) 定位UTC 时间:08 时20 分06 秒

(2) 纬度(格式ddmm.mmmm:即dd 度,mm.mmmm 分);

(3) N/S(北纬或南纬):北纬38 度52.9276 分;

(4) 经度(格式dddmm.mmmm:即ddd 度,mm.mmmm 分);

(5) E/W(东经或西经):东经115 度27.4283 分;

(6) 质量因子(0=没有定位,1=实时GPS,2=差分GPS):1=实时GPS;

(7) 可使用的卫星数(0~8):可使用的卫星数=08;

(8) 水平精度因子(1.0~99.9);水平精度因子=1.0;

(9) 天线高程(海平面,-9999.9~99999.9,单位:m);天线高程=20.6m);

(10) 大地椭球面相对海平面的高度(-999.9~9999.9,单位:m):无;

(11) 差分GPS 数据年龄,实时GPS 时无:无;

(12) 差分基准站号(0000~1023),实时GPS 时无:无;

*总和校验域;hh 总和校验数:35(CR)(LF)回车,换行。

GPRMC(建议使用最小GPS 数据格式)

$GPRMC,082006.000,A,3852.9276,N,11527.4283,E,0.00,0.0,261009,,*38

$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11><CR><LF>

(1) 标准定位时间(UTC time)格式:时时分分秒秒.秒秒秒(hhmmss.sss)。

(2) 定位状态,A = 数据可用,V = 数据不可用。

(3) 纬度,格式:度度分分.分分分分(ddmm.mmmm)。

(4) 纬度区分,北半球(N)或南半球(S)。

(5) 经度,格式:度度分分.分分分分。

(6) 经度区分,东(E)半球或西(W)半球。

(7) 相对位移速度, 0.0 至1851.8 knots

(8) 相对位移方向,000.0 至359.9 度。实际值。

(9) 日期,格式:日日月月年年(ddmmyy)。

(10) 磁极变量,000.0 至180.0。

(11) 度数。

(12) Checksum.(检查位)

$GPVTG 地面速度信息

例:$GPVTG,0.0,T,,M,0.00,N,0.0,K*50

字段0:$GPVTG,语句ID,表明该语句为Track Made Good and Ground Speed(VTG)地

面速度信息

字段1:运动角度,000 - 359,(前导位数不足则补0)

字段2:T=真北参照系

字段3:运动角度,000 - 359,(前导位数不足则补0)

字段4:M=磁北参照系

字段5:水平运动速度(0.00)(前导位数不足则补0)

字段6:N=节,Knots

字段7:水平运动速度(0.00)(前导位数不足则补0)

字段8:K=公里/时,km/h

字段9:校验值

表 1 GPS模块主要参数


GPS模块主要参数


GPS

芯片组


SiRF Star III


工作频率


L1, 1575.42 MHz


粗捕获码 
(C/A)率


1.023 MHz chip rate


同时跟踪通道数


20


灵敏度


-159 dBm


定位精度


5m(2维均方根, 允许广域差分系统)


最小速度


0.1 m/s


时间精度


1μS(与GPS时间同步)


默认

坐标系


1984年世界大地坐标系(WGS-84)


重获时间


0.1S(平均值)


热启动


1S(平均值)


温启动


38S(平均值)


冷启动


42S(平均值)


最高工作海拔


18km(60000feet)


最大

移动速率


515m/S(1000knots)


最大加速度


4g


最大

急冲度


20m/S3


电源电压


5V±0.5V


整机电流


约60mA,不超过100mA


整板外形


61mm×49mm×17mm


GPS

芯片外形


27.9mm×20mm×2.9mm


波特率


9600bps


数据输出格式


SiRF二进制格式或NMEA 0183 GGA, GSA, GSV, RMC,VTG,GLL


数据输出电平


同时具备TTL电平和RS232电平


数据

输出接口


20pin插针(TTL电平)和DB9母座 
(RS232电平)


天线类型


外置有源GPS天线(3.3V/5V电压可选, 
默认为3.3V)


后备电池


CR1220锂电池,3V,不可充电


工作温度


-40ºC至+85ºC

GPS模块的应用程序设计

GPS模块的应用程序设计主要分为两部分,第一部分为串口的设置于数据读取,第二部分为数据的分析和需要数据的提取。

与其他的关于设备编程的方法一样,在Linux下,操作、控制串口也是通过操作起设备文件进行的。在Linux下,串口的设备文件是/dev/ttyS0或/dev/ttyS1等。因此要读写串口,我们首先要打开串口,然后根据GPS模块的配置参数对串口的波特率、校验、流控制等进行设置,这些参数设置均通过对termios结构中c_cflag的配置实现,串口配置部分函数如下:

int gps::set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
    struct termios newtio,oldtio;
    if  ( tcgetattr( fd,&oldtio)  !=  0)
    {
        perror("SetupSerial 1");
        return -1;
    }
    bzero( &newtio, sizeof( newtio ) );
    newtio.c_cflag  |=  CLOCAL | CREAD;
    newtio.c_cflag &= ~CSIZE;

    switch( nBits )
    {
    case 7:
        newtio.c_cflag |= CS7;
        break;
    case 8:
        newtio.c_cflag |= CS8;
        break;
    }

    switch( nEvent )
    {
    case ‘O‘:                     //奇校验
        newtio.c_cflag |= PARENB;
        newtio.c_cflag |= PARODD;
        newtio.c_iflag |= (INPCK | ISTRIP);
        break;
    case ‘E‘:                     //偶校验
        newtio.c_iflag |= (INPCK | ISTRIP);
        newtio.c_cflag |= PARENB;
        newtio.c_cflag &= ~PARODD;
        break;
    case ‘N‘:                    //无校验
        newtio.c_cflag &= ~PARENB;
        break;
    }

switch( nSpeed )
    {
    case 2400:
        cfsetispeed(&newtio, B2400);
        cfsetospeed(&newtio, B2400);
        break;
    case 4800:
        cfsetispeed(&newtio, B4800);
        cfsetospeed(&newtio, B4800);
        break;
    case 9600:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    case 115200:
        cfsetispeed(&newtio, B115200);
        cfsetospeed(&newtio, B115200);
        break;
    default:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    }
    if( nStop == 1 )
    {
        newtio.c_cflag &=  ~CSTOPB;
    }
    else if ( nStop == 2 )
    {
        newtio.c_cflag |=  CSTOPB;
    }
    newtio.c_cc[VTIME]  = 0;
    newtio.c_cc[VMIN] = 0;
    tcflush(fd,TCIFLUSH);
    if((tcsetattr(fd,TCSANOW,&newtio))!=0)
    {
        qDebug()<<"com set error"<<endl;
        return -1;
    }
    qDebug()<<"set done!"<<endl;
    return 0;
}

在GPS数据的处理上首先将窗口数据存入一个字符串,接着通过对字符串数据的判断来提取数据内容,判断分为两步,首先判断是什么类型的数据,在本程序的设计中需要读取$GPRMC和$GPGGA两组数据,因此首先判断字符串GPS_BUF[5]是C还是A,由于数据是通过符号“,”进行隔开,因此通过查找“,”来确定数据位置。在实现上将得到逗号位置函数单独封装调用,程序如下:

//得到指定序号的逗号位置
int gps::GetComma(int num,char *str)
{
    int i,j=0;
    int len=strlen(str);
    for(i=0;i<len;i++)
    {
        if(str[i]==‘,‘)
        {
             j++;
        }

        if(j==num)
            return i+1;
    }
    return 0;
}

接下来根据数据格式,通过逗号位置,提取数据信息,程序如下:

void gps::gps_parse()
{
    int tmp;
    char c;

    c = GPS_BUF[5];
    if(c==‘C‘)
    {
        //"GPRMC"
        GPS->D.hour   =(GPS_BUF[ 7]-‘0‘)*10+(GPS_BUF[ 8]-‘0‘);
        GPS->D.minute =(GPS_BUF[ 9]-‘0‘)*10+(GPS_BUF[10]-‘0‘);
        GPS->D.second =(GPS_BUF[11]-‘0‘)*10+(GPS_BUF[12]-‘0‘);
        tmp = GetComma(9,GPS_BUF);
        GPS->D.day    =(GPS_BUF[tmp+0]-‘0‘)*10+(GPS_BUF[tmp+1]-‘0‘);
        GPS->D.month  =(GPS_BUF[tmp+2]-‘0‘)*10+(GPS_BUF[tmp+3]-‘0‘);
        GPS->D.year   =(GPS_BUF[tmp+4]-‘0‘)*10+(GPS_BUF[tmp+5]-‘0‘)+2000;

        GPS->status      = GPS_BUF[GetComma(2,GPS_BUF)];
        GPS->latitude = get_locate(get_double_number(&GPS_BUF[GetComma(3,GPS_BUF)]));
        GPS->NS       = GPS_BUF[GetComma(4,GPS_BUF)];
        GPS->longitude= get_locate(get_double_number(&GPS_BUF[GetComma(5,GPS_BUF)]));
        GPS->EW       = GPS_BUF[GetComma(6,GPS_BUF)];
        GPS->speed    = get_double_number(&GPS_BUF[GetComma(7,GPS_BUF)]);
        UTC2BTC(&GPS->D);

    }

    if(c==‘A‘)
    {
        //"$GPGGA"
        GPS->high     = get_double_number(&GPS_BUF[GetComma(9,GPS_BUF)]);
    }

 }
//将获取文本信息转换为double型

double gps::get_double_number(char *s)
{
    char buf[128];
    int i;
    double rev;
    i=GetComma(1,s);
    strncpy(buf,s,i);
    buf[i]=0;
    rev=atof(buf);

    return rev;
}

double gps::get_locate(double temp)
{
    int m;
    double  n;
    m=(int)temp/100;
    n=(temp-m*100)/60;
    n=n+m;
    return n;

}
时间: 2024-08-12 10:44:17

GPS数据读取与处理的相关文章

GPS数据解析

1.摘要 GPS模块使用串口通信,那么它的的数据处理本质上还是串口通信处理,只是GPS模块的输出的有其特定的格式,需要字符串处理逻辑来解析其含义.如何高效的处理从GPS模块接收到的数据帧,是GPS驱动设计的重点,本文使用状态机的思想来处理GPS输出的串口数据流,相对于定时从串口环形bufer取数据包然后依次解析有更高的实时性并且单片机负荷更低. 2. GPS数据协议简介 常用的GPS模块大多采用NMEA-0183 协议,目前业已成了GPS导航设备统一的RTCM(Radio Technical C

使用Socket通信实现Silverlight客户端实时数据的获取(模拟GPS数据,地图实时位置)

原文:使用Socket通信实现Silverlight客户端实时数据的获取(模拟GPS数据,地图实时位置) 在上一篇中说到了Silverlight下的Socket通信,在最后的时候说到本篇将会结合地图.下面就来看看本文实现的功能: Silverlight 与服务器利用Socket通讯,实时从服务器获取数据(本文中的数据是地理坐标),由于没有GPS,所以本文在服务器写了一个构造新坐标的函数(本文是一个三角函数),然后利用Timer组件,实时调用,得到新的坐标,并将新的坐标发送给客户端,客户端接收到发

DataReader对象(数据读取)

DataReader对象提供了一个只进只读的数据读取器,用于从查询结果中读取数据,它每次仅能读取一行数据. [常用属性]: FieldCount:获取当前行的列数: HasRows:表明查询结果中是否还存在未被读取的数据. [常用方法]: Close:关闭SqlDataReader对象: GetName:获取指定列的名称; Read:使SqlDataReader前进到下一条记录. [使用DataReader对象对数据库进行查询操作步骤]: 1.创建Connection对象: 2.打开数据库连接:

sas数据读取详解 四种读取数据方式以及数据指针的位置 、读取mess data的两个小工具、特殊的读取技巧、infile语句及其选项(dsd dlm missover truncover obs firstobs)、proc import、自定义缺失值

(The record length is the number of characters, including spaces, in a data line.) If your data lines are long, and it looks like SAS is not reading all your data, then use the LRECL= option in the INFILE statement to specify a record length at least

转载---CGImageSource对图像数据读取任务的抽象

转载地址:http://www.tanhao.me/pieces/1019.html CGImageSource是对图像数据读取任务的抽象,通过它可以获得图像对象.缩略图.图像的属性(包括Exif信息). 1.创建CGImageSourceRef 1 2 NSString *imagePath = [[NSBundle bundleForClass:self.class] pathForImageResource:@"test.png"]; CGImageSourceRef image

T31P电子秤数据读取

连接串口后先发送"CP\r\n"激活电子秤数据发送,收到的数据包是17字节的 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DotNet.ElecScales { using System.IO.Ports; using System.Text; using System.Threading; /// <summary> ///

工大助手--数据读取

工大助手--数据读取 实现功能 1)用户可选择获取入学以来所有已修课程的相关信息:课程代号.课程名.课程属性.学分.成绩等信息. 2)用户可选择获取特定已修课程的相关信息:课程代号.课程名.课程属性.学分.成绩等信息. 3)用户可获得特定时间段内的加权平均分(1学期.1学年.全部). 团队成员 13070003 张   帆 13070046 孙宇辰 13070004 崔   巍 13070006 王   奈 13070002 张雨帆 13070045 汪天米 数据读入 在上次博客中,我讲到了我所

android SharedPreferences简单应用 插入数据 读取数据

package com.sharedpreference; import java.text.SimpleDateFormat; import java.util.Date; import android.os.Bundle; import android.app.Activity; import android.content.SharedPreferences; import android.view.Menu; import android.view.View; import androi

10 张图帮你搞定 TensorFlow 数据读取机制

导读 在学习tensorflow的过程中,有很多小伙伴反映读取数据这一块很难理解.确实这一块官方的教程比较简略,网上也找不到什么合适的学习材料.今天这篇文章就以图片的形式,用最简单的语言,为大家详细解释一下tensorflow的数据读取机制,文章的最后还会给出实战代码以供参考. 一.tensorflow读取机制图解 首先需要思考的一个问题是,什么是数据读取?以图像数据为例,读取数据的过程可以用下图来表示: 假设我们的硬盘中有一个图片数据集0001.jpg,0002.jpg,0003.jpg--我