欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

第8章 USB-4G/LTE移植 -第3节 USB-4G移植(移远AG35开发-GPS解析及编程)

程序员文章站 2024-01-27 15:48:16
...

查看参考手册,移远带有GPS的芯片的USB Serial如下。

第8章 USB-4G/LTE移植 -第3节 USB-4G移植(移远AG35开发-GPS解析及编程)

2.1应用简介

1、若不使用 AT+QGPSCFG 指令对AG35进行配置,则会以默认参数开启GPS参数,NMEA端口开始上报,”gpsnmeatype”默认值为31,上报间隔为1s,每次上报所有种类的NMEA数据(GGA\RMC\GSV\GSA\VTG),若采用此默认配置,大多数使用者会觉得单次上报的数据太多且很多信息重复,建议大家使用QGPSCFG配置自己需要的NMEA数据格式,具体格式的差异可参考网上对NMEA数据的说明。
2、Linux环境下对NMEA数据的获取:
cat /dev/ttyUSB1 & // NMEA数据从ttyUSB1输出
echo “AT+QGPS=1” > /dev/ttyUSB2 // 开启GPS会话
可观察到ttyUSB1输出NMEA数据,如下:
第8章 USB-4G/LTE移植 -第3节 USB-4G移植(移远AG35开发-GPS解析及编程)
3、程序设计过程中,若有固定频率更新位置需求,可考虑采用读取NMEA端口数据的形式,并将其配置适合自己需求的NMEA格式和数据更新间隔。若产品执行获取位置指令的频率较低且间隔时间不固定,也可考虑直接在AT指令端口使用AT+QGPSLOC指令进行实时位置信息的获取。

2.2 GPS数据解析

NMEA 0183是美国国家海洋电子协会(National Marine Electronics Association )为海用电子设备制定的标准格式。目前业已成了GPS导航设备统一的RTCM(Radio Technical Commission for Maritime services)标准协议。
GPS接收机上电后,会自动通过串口或USB口发送NMEA0183格式的数据包,它是一组包含有各种地理位置信息的字符串,字符串格式为:
$信息类型,xxx,xxx,xxx,xxx,xxx,xxx,xxx,
每行开头的字符都是‘$’,接着是信息类型,后面是数据,以逗号分隔开。一行完整的数据如下:
$GPRMC,063102.00,A,2932.293196,N,10636.147385,E,0.0,45.5,250818,2.3,W,A*10

信息类型为:
GPVTG:地面速度信息
GPRMC:推荐最小定位信息
GPGSA:当前卫星信息
GPGGA:GPS定位信息
GPGSV:可见卫星信息
这里我们只解析GPRMC和GPGGA的信息。

 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.时间,这个是格林威治时间,是世界时间(UTC),我们需要把它转换成北京时间(BTC),BTC和UTC差了8个小时,要在这个时间基础上加8个小时。
2.定位状态,在接收到有效数据前,这个位是‘V’,后面的数据都为空,接到有效数据后,这个位是‘A’,后面才开始有数据。
3.纬度,我们需要把它转换成度分秒的格式,计算方法:
如接收到的纬度是:4546.40891
4546.40891 / 100 = 45.4640891 可以直接读出45度
4546.40891–45 * 100 = 46.40891 可以直接读出46分
46.40891–46 = 0.40891 * 60 = 24.5346 读出24秒
所以纬度是:45度46分24秒。

4.南北纬,这个位有两种值‘N’(北纬)和‘S’(南纬)
5.经度的计算方法和纬度的计算方法一样
6.东西经,这个位有两种值‘E’(东经)和‘W’(西经)
7.速率,这个速率值是 海里/时,单位是节,要把它转换成千米/时,根据:1海里 = 1.85公里,把得到的速率乘以1.85。
8.航向,指的是偏离正北的角度
9.日期,这个日期是准确的,如:200818表示2018年08月20日,这个日期是准确的,不需要转换。

 GPGGA数据详解
$GPGGA,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,M,<10>,M,<11>,<12>*xx
$GPGGA:起始引导符及语句格式说明(本句为GPS定位数据);
<1> UTC时间,格式为hhmmss.sss;
<2> 纬度,格式为ddmm.mmmm(第一位是零也将传送);
<3> 纬度半球,N或S(北纬或南纬)
<4> 经度,格式为dddmm.mmmm(第一位零也将传送);
<5> 经度半球,E或W(东经或西经)
<6> 定位质量指示,0=定位无效,1=定位有效;
<7> 使用卫星数量,从00到12(第一个零也将传送)
<8> 水平精确度,0.5到99.9
<9> 天线离海平面的高度,-9999.9到9999.9米 M 指单位米
<10> 大地水准面高度,-9999.9到9999.9米 M 指单位米
<11> 差分GPS数据期限(RTCM SC-104),最后设立RTCM传送的秒数量
<12> 差分参考基站标号,从0000到1023(首位0也将传送)。

2.3 GPS编程

GPS解析主要有两个部分,一个是USB转串口的配置,另外一个就是GPS的解析。下面就一一介绍。
1.串口配置
由于我是通过串口来进行数据传输,也就是把GPS定位的信息,通过串口最后输出到我们的终端设备上。
【uart_GPS_config.c】

/**
  ******************************************************************************
  * @file    uart_GPS_config.c
  * @author  Bruceou
  * @version V1.0
  * @date    2018.04.11
  * @brief   串口设置
  ******************************************************************************
  */
/**Includes*********************************************************************/
#include "uart_GPS_config.h"

/**
  * @brief     串口设置函数
  * @param     fd
               baud_rate
               data_bits
               parity
               stop_bits
  * @retval    int
  */
 int set_GPS_com_config(int fd,int baud_rate,int data_bits, char parity, int stop_bits) 
{
    struct termios new_cfg;
    int speed;

    /* 保存并测试现有串口参数设置,在这里如果串口号等出错,会有相关的出错信息 */

    if (tcgetattr(fd, &new_cfg) != 0) 
    {
        perror("tcgetattr save");   
        return -1;
    }

    //修改控制模式,保证程序不会占用串口  
    new_cfg.c_cflag |= CLOCAL;  
    //修改控制模式,使得能够从串口中读取输入数据  
    new_cfg.c_cflag |= CREAD;  
    new_cfg.c_oflag &= ~(ONLCR | OCRNL);
    new_cfg.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
    new_cfg.c_iflag &= ~(ICRNL | INLCR);
    new_cfg.c_iflag &= ~(IXON | IXOFF | IXANY);

    /* 设置波特率 */
    switch (baud_rate)
    {
        case 2400:  
        {
            speed = B2400;  
        }
        break;      
        case 4800:
        {
            speed = B4800;
        }
        break;
        case 9600:
        {
            speed = B9600;
        }
        break;
        case 19200:
        {
            speed = B19200;
        }
        break;
        case 38400: 
        {
            speed = B38400;
        }
        break;
        default:            
        case 115200:        
        {
            speed = B115200;            
        }       
        break;      
    }

    cfsetispeed(&new_cfg, speed);//输入波特率    
    cfsetospeed(&new_cfg, speed);//输出波特率
    switch (data_bits) /* 设置数据位 */  
    {       
        case 7:
        {
            new_cfg.c_cflag |= CS7;     
        }       
        break;  
        default:    
        case 8:
        {
            new_cfg.c_cflag |= CS8;
        }       
        break;      
    }

    switch (parity) /* 设置奇偶校验位 */   
    {
        default:    
        case 'n':   
        case 'N':   
        {
            new_cfg.c_cflag &= ~PARENB; 
            new_cfg.c_iflag &= ~INPCK;     
        }   
        break;  
        case 'o':
        case 'O':
        {
            new_cfg.c_cflag |= (PARODD | PARENB); 
            new_cfg.c_iflag |= INPCK; 
        }   
        break;      
        case 'e':
        case 'E':
        {
            new_cfg.c_cflag |= PARENB; 
            new_cfg.c_cflag &= ~PARODD; 
            new_cfg.c_iflag |= INPCK; 

        }   
        break;          
        case 's': /* as no parity */        
        case 'S':
        {
            new_cfg.c_cflag &= ~PARENB;
            new_cfg.c_cflag &= ~CSTOPB;
        }   
        break;  
    }
    switch (stop_bits) /* 设置停止位 */  
    {
        default:
        case 1:
        {
            new_cfg.c_cflag &= ~CSTOPB;        
        }   
        break;  
        case 2:
        {
            new_cfg.c_cflag |= CSTOPB;      
        }
    }
    //修改输出模式,原始数据输出  
    new_cfg.c_oflag &= ~OPOST;  
    new_cfg.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);//我加的  
    new_cfg.c_lflag &= ~(ISIG | ICANON);  

    //设置等待时间和最小接收字符  
    new_cfg.c_cc[VTIME] = 0; /* 读取一个字符等待0*(0/10)s */    
    new_cfg.c_cc[VMIN] = 1; /* 读取字符的最少个数为0 */  

    //如果发生数据溢出,接收数据,但是不再读取 刷新收到的数据但是不读
    tcflush(fd, TCIFLUSH); /* 处理未接收字符 */    
    if ((tcsetattr(fd, TCSANOW, &new_cfg)) != 0) /* **新配置 */    
    {
        perror("tcsetattr action");
        return -1;  
    } 
    //printf("serial set success\n");
    return 0;   
}

/**
  * @brief     打开串口函数
  * @param     com
  * @retval    int
  */
int open_GPS_port(const char *com_port)
{
    int fd;

    /*分别为com1,com2, com3对应 ttyS0 ttyS1 ttyS2 */             
    fd = open( com_port, O_RDWR|O_NOCTTY|O_NDELAY);          
    if (fd < 0)  
    {
        perror("Can't Open Serial Port");  
        return -1;                                           
    }
    /*恢复串口为阻塞状态*/
    if (fcntl(fd,F_SETFL,0)<0)
    {
        perror("fcntl F_SETFL\n");
    }
    /*测试是否为终端设备*/
    if(isatty(STDIN_FILENO) == 0)
    {
        perror("standard input is not a terminal device");
    }
    return fd;
}

/**
  * @brief     串口初始化函数
  * @param     com_port
  * @retval    int
  */
int init_GPS_port(const char *com_port)
{
    int fd;

    if ((fd = open_GPS_port(com_port)) < 0 )
    {
        perror("open_port");
        return -1;
    }

    if(set_GPS_com_config(fd,9600,8,'N',1) < 0)
    {
        perror("set_com_config");
        return -1;
    }
    return fd;
}

【uart_GPS_config.h】

#ifndef _UART_GPS_CONFIG_H_
#define _UART_GPS_CONFIG_H_

#include<errno.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include <termios.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include <ctype.h>

#define BUFFER_SIZE  36

#define DEVICE_AT_GPS        "/dev/ttyUSB2"
#define DEVICE_DATA_GPS      "/dev/ttyUSB1"

int set_GPS_com_config(int fd,int baud_rate, int data_bits,char parity,int stop_bits);
int open_GPS_port(const char *com_port);
int init_GPS_port(const char *com_port);

#endif

2.GPS数据分析
【GPS.c】

/**
  ******************************************************************************
  * @file    GPS.c
  * @author  Bruceou
  * @version V1.0
  * @date    2018.08.11
  * @brief   GPS 解析
  ******************************************************************************
  */
/**Includes*********************************************************************/
#include "GPS.h"

char *buff = NULL;

GPRMC_t gprmc;
GPGGA_t gpgga;

/**
  * @brief     GPS解析函数
  * @param     AT_fd:串口文件描述符
  * @          DATA_fd:串口文件描述符
  * @retval    Nono
  */
void GPS_Analysis(int AT_fd,int DATA_fd)
{
    int  nread,nwrite;
    char send_buff[16];
    char recv_buff[512];
    char *ptr = NULL;
    char AT_Buff[16];
    int ret = 0;
#if 0
    uint32_t time  =0;
    uint32_t lat   =0 ;
    uint32_t lon   =0;
    uint32_t speed =0;
    uint32_t head  =0;
    uint32_t alt   =0;
#endif

    while(1)
    {
        memset(AT_Buff,0,sizeof(AT_Buff));
        strcpy(AT_Buff, "AT+QGPS=1");
        GPS_Set(AT_fd , AT_Buff);

        if(buff != NULL)
        {
            break;
        }

        memset(AT_Buff,0,sizeof(AT_Buff));
        strcpy(AT_Buff, "AT+QGPSEND");
        GPS_Set(AT_fd , AT_Buff);
        sleep(1);
    }

    //接收数据
    while(1)
    {
        memset(&gprmc, 0, sizeof(gprmc));
        memset(&gpgga, 0, sizeof(gpgga));
        memset(recv_buff,0,sizeof(recv_buff));
        nread = read(DATA_fd,recv_buff,sizeof(recv_buff));

#ifdef DEBUG_GPS    
        printf("nread=%d,%s\n",nread,recv_buff);
        printf("=================2===================\n");
#endif
        //strcpy(buff, recv_buff);
        //保存数据
        ptr = strstr(recv_buff, "$GPRMC");
        ret = sscanf(ptr, "$GPRMC,%f,%c,%f,%*c,%f,%*c,%f,%f,%d,%f,%*c,%*c*", 
                                  &gprmc.time,&gprmc.state, &gprmc.lat, &gprmc.lon,
                                  &gprmc.speed, &gprmc.head, &gprmc.date,&gprmc.dec);

        ptr = strstr(recv_buff, "$GPGGA");
        ret = sscanf(ptr, "$GPGGA,%f,%f,N,%f,E,%d,%d,%f,%f,M,%f,M,,*", 
                                  &gpgga.time, &gpgga.lat, &gpgga.lon,
                                  &gpgga.state, &gpgga.num, &gpgga.hdop, &gpgga.alt, &gpgga.geoid);
#if 0       
        time = (int)(gprmc.time*100) % 100   + ((int)gprmc.time % 100) * 100 +\
               ((int)gprmc.time%10000/100) *60 * 100 + ((int)gprmc.time/10000)* 3600 * 100;

        lat     =  ((int)(gprmc.lat/100) + (gprmc.lat-(int)gprmc.lat/100*100)/60)*10000000;
        lon     = ((int)(gprmc.lon/100) + (gprmc.lon-(int)gprmc.lon/100*100)/60)*10000000;
        speed   = gprmc.speed* 1.852;
        head    = gprmc.head;

        alt     = gpgga.alt;
#endif  
        //打印数据
        print_GPS_RMC(&gprmc);
        print_GPS_GGA(&gpgga);          
    }
}

/**
  * @brief     GPS打开函数
  * @param     AT_fd:串口文件描述符
  * @          AT :AT指令
  * @retval    Nono
  */
void GPS_Set(int AT_fd,char *AT)
{
    int  nread,nwrite;
    char send_buff[16];
    char recv_buff[64];

    memset(send_buff,0,sizeof(send_buff));
    strcpy(send_buff, AT);
    strcat(send_buff,"\r");
    nwrite = write(AT_fd,send_buff,strlen(send_buff));

#ifdef DEBUG_GPS
    printf("nwrite=%d,%s\n",nwrite,send_buff);
#endif
    //waiting for AT's ACK等待回应
    memset(recv_buff,0,sizeof(recv_buff));
    nread = read(AT_fd,recv_buff,sizeof(recv_buff));

    buff = strstr(recv_buff,"OK");
    //memset(buff,0,strlen(buff));

#ifdef DEBUG_GPS    
    printf("nread=%d,%s\n",nread,recv_buff);
    printf("================1======================\n");
#endif

}

/**
  * @brief     GPS-RMC信息打印
  * @param     gprmc_data:
  * @retval    Nono
  */
void print_GPS_RMC(GPRMC_t *gprmc_data)
{
    printf("                                                           \n");
    printf("===========================================================\n");
    printf("==              全球GPS定位导航模块                      ==\n");
    printf("==              Author:BruceOu                          ==\n");
    printf("==              Email:aaa@qq.com                   ==\n");
    printf("================RMC信息====================================\n");
    printf("===========================================================\n");
    printf("==   GPS state bit : %c  [A:有效状态 V:无效状态]           \n",gprmc_data->state);
    printf("==   Date : 20%02d-%02d-%02d                               \n",gprmc_data->date%100,(gprmc_data->date%10000)/100,gprmc_data->date/10000);
    printf("==   纬度 : 北纬:%d度%d分%d秒                              \n",((int)gprmc_data->lat) / 100, (int)(gprmc_data->lat - ((int)gprmc_data->lat / 100 * 100)), (int)(((gprmc_data->lat - ((int)gprmc_data->lat / 100 * 100)) - ((int)gprmc_data->lat - ((int)gprmc_data->lat / 100 * 100))) * 60.0));
    printf("==   经度 : 东经:%d度%d分%d秒                              \n",((int)gprmc_data->lon) / 100, (int)(gprmc_data->lon - ((int)gprmc_data->lon / 100 * 100)), (int)(((gprmc_data->lon - ((int)gprmc_data->lon / 100 * 100)) - ((int)gprmc_data->lon - ((int)gprmc_data->lon / 100 * 100))) * 60.0));
    printf("==   速度 : %.3f  m/s                                      \n",gprmc_data->speed * 1.852);
    printf("==   航向 : %.3f  度                                       \n",gprmc_data->head );
    printf("===========================================================\n");

}

/**
  * @brief     GPS-GGA信息打印
  * @param     gpgga_data:
  * @retval    Nono
  */
void print_GPS_GGA(GPGGA_t *gpgga_data)
{
    printf("                                                           \n");
    printf("===========================================================\n");
    printf("==              全球GPS定位导航模块                      ==\n");
    printf("==              Author:BruceOu                          ==\n");
    printf("==              Email:aaa@qq.com                   ==\n");
    printf("================GGA信息====================================\n");
    printf("===========================================================\n");
    printf("==   纬度 : 北纬:%d度%d分%d秒                              \n",((int)gpgga_data->lat) / 100, (int)(gpgga_data->lat - ((int)gpgga_data->lat / 100 * 100)), (int)(((gpgga_data->lat - ((int)gpgga_data->lat / 100 * 100)) - ((int)gpgga_data->lat - ((int)gpgga_data->lat / 100 * 100))) * 60.0));
    printf("==   经度 : 东经:%d度%d分%d秒                              \n",((int)gpgga_data->lon) / 100, (int)(gpgga_data->lon - ((int)gpgga_data->lon / 100 * 100)), (int)(((gpgga_data->lon - ((int)gpgga_data->lon / 100 * 100)) - ((int)gpgga_data->lon - ((int)gpgga_data->lon / 100 * 100))) * 60.0));
    printf("==   数量 : %d    颗                                       \n",gpgga_data->num);
    printf("==   精度 : %.3f                                           \n",gpgga_data->hdop);
    printf("==   海拔 : %.3f  m                                        \n",gpgga_data->alt);
    printf("===========================================================\n");
}

【GPS.h】

#ifndef _GPS_H_
#define _GPS_H_

#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <assert.h>
#include <iconv.h>
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include "uart_GPS_config.h"

#define DEBUG_GPS

typedef unsigned char  uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int   uint32_t;

typedef struct _GPRMC
{
    float       time;//UTC时间,hhmmss(时分秒)格式/* gps定位时间 */
    uint8_t     state;/*gps状态位*//*A=有效定位,V=无效定位*/
    float       lat;/*纬度 */
    float       lon;/* 经度 */
    float       speed;/*速度 */
    float       head;/*航向 */
    uint32_t    date;/*日期*/
    float       dec;/* 磁偏角 */
    uint8_t     dd;/*磁偏角方向*/
    uint8_t     mode;/*GPS模式位*//*A=自主定位,D=差分,E=估算,N=数据无效*/
}GPRMC_t;

typedef struct _GPGGA
{
    float       time;//UTC时间,hhmmss(时分秒)格式/* gps定位时间 */
    float       lat;/*纬度 */
    float       lon;/* 经度 */
    uint32_t    state;/*gps状态位*//*0=定位无效,1=定位有效;*/
    uint32_t    num;/*使用卫星数量,从00到12(第一个零也将传送)*/
    float       hdop;/*水平精确度,0.5到99.9*/
    float       alt;/*天线离海平面的高度,-9999.9到9999.9米*/
    float       geoid;
}GPGGA_t;

void GPS_Analysis(int AT_fd,int DATA_fd);
void GPS_Set(int AT_fd,char *AT);
void print_GPS_RMC(GPRMC_t *gprmc_data);
void print_GPS_GGA(GPGGA_t *gpgga_data);

#endif 

【注意】
1.由于我直接获取的是格林威治时间即世界时间(UTC),所以要把它转换成北京时间(BTC),也就是在这个时间基础上加8个小时。
2.经纬度,GPRMC返回的纬度数据位ddmm.mmmm格式即度分格式,我们把它转换成常见的度分秒的格式,计算方法:如接收到的纬度是:3029.60430
3029.60430/100=
30.2960430可以直接读出30度, 3029.60430–30*100=29.60430, 可以直接读出29分 (29.60430–29)*60 =0.60430*60=36.258读出36秒, 所以纬度是:30度29分36秒。
3.GPRMC返回的速率值是海里/时,单位是节,把它转换成千米/时,换算为:1海里=1.85公里,把得到的速率乘以1.85。
4.航向指的是偏离正北的角度。
5.GPRMC的日期格式为:ddmmyy,如:200818表示2018年08月20日,这个日期是准确的,不需要转换。

3.主函数打开串口设备读操作
【main.c】

 /**
  ******************************************************************************
  * @file    main.c
  * @author  Bruceou
  * @version V1.0
  * @date    2018.08.11
  * @brief   
  ******************************************************************************
  */
/**Includes*********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>  
#include <sys/stat.h>  
#include <sys/types.h>  
#include "uart_GPS_config.h"
#include "GPS.h"

#define DEBUG_GPS

int GPS_DATA_fd = -1;                 //GPS_DATA描述符 
int GPS_AT_fd = -1;                   //GPS_AT描述符;  

/**
  * @brief     main函数
  * @param     Nono
  * @retval    Nono
  */
int main(int argc, char **argv)
{
    GPS_AT_fd = init_GPS_port(DEVICE_AT_GPS);      //初始化AT GPS

    if(GPS_AT_fd < 0)
    {
        printf("open GPS_AT_port failed!\n");
    }
    else
    {
        printf("open GPS_AT_port success!\n");
    }

    GPS_DATA_fd = init_GPS_port(DEVICE_DATA_GPS);      //初始化DATA GPS

    if(GPS_AT_fd < 0)
    {
        printf("open GPS_DATA_port failed!\n");
    }
    else
    {
        printf("init GPS_port success!\n");
        GPS_Analysis(GPS_AT_fd,GPS_DATA_fd);
    }

    return 0;
}

【注】AG35的USB转串口信息在本文前已经给出,需要使用两个设备,ttyUSB1和ttyUSB2,ttyUSB1是GPS输出信息,ttyUSB2是AT命令配置设备,因此需要打开两个设备。
【Makefile】

APPS := gps_app
CC := arm-fsl-linux-gnueabi-gcc#交叉编译工具

srcs := *.c 

all:$(srcs)
    $(CC) $(srcs) -o $(APPS) 
clean:
    rm $(APPS)

4.测试
编译完成后,执行程序,会有下面的主要信息,可以看到GPS的解析数据。
第8章 USB-4G/LTE移植 -第3节 USB-4G移植(移远AG35开发-GPS解析及编程)
第8章 USB-4G/LTE移植 -第3节 USB-4G移植(移远AG35开发-GPS解析及编程)
第8章 USB-4G/LTE移植 -第3节 USB-4G移植(移远AG35开发-GPS解析及编程)
参考:

Quectel_EC20_GNSS_AT_Commands_Manual_V1.1.pdf
NMEA码详解:http://www.gpsbaby.com/wz/nmea.html