搜索
bottom↓
回复: 90

转载:如何利用strstr和sscanf解析GPS信息

  [复制链接]

出0入0汤圆

发表于 2010-9-4 15:21:02 | 显示全部楼层 |阅读模式
直接复制:
作者:杨硕,华清远见嵌入式学院讲师。
  
  做一个GPS导航的项目,需要读取GPS模块以ASCII码的形式发送过来的数据,然后对这些数据进行处理,提取我们需要的信息。这就涉及到很多操作字符串的问题。下面就以此为例,利用strstr函数和sscanf函数解析GPS数据。
    关于sscanf函数请见http://www.91linux.com/html/article/program/cpp/20081130/14121.html
  GPS输出的数据格式如下:

  $GPGGA,121252.000,3937.3032,N,11611.*6,E,1,05,2.0,45.9,M,-5.7,M,,0000*77

  $GPRMC,121252.000,A,3958.3032,N,11629.*6,E,15.15,359.95,070306,,,A*54

  $GPVTG,359.95,T,,M,15.15,N,28.0,K,A*04

  $GPGGA,121253.000,3937.3090,N,11611.6057,E,1,06,1.2,44.6,M,-5.7,M,,0000*72

  $GPGSA,A,3,14,15,05,22,18,26,,,,,,,2.1,1.2,1.7*3D

  $GPGSV,3,1,10,18,84,067,23,09,67,067,27,22,49,312,28,15,47,231,30*70

  $GPGSV,3,2,10,21,32,199,23,14,25,272,24,05,21,140,32,26,14,070,20*7E

  $GPGSV,3,3,10,29,07,074,,30,07,163,28*7D

  可以看到,GPS模块发送过来的原始数据有很多,但是通常我们只需要其中的一部分信息就够用了,比如对于导航的功能,我们只需要以$GPRMC开头,以换行符结束的一行信息就够了。即:

  $GPRMC,121252.000,A,3958.3032,N,11629.*6,E,15.15,359.95,070306,,,A*54

  因此我们需要做的就是从读取的数据中截取以$GPRMC开头的一行信息,然后从中解析出经纬度、日期时间等有效信息即可。

  假设从串口读取的数据存放在一个字符串指针char *raw_buf指向的内存单元里,首先我们通过ANSI C提供的strstr()函数找到以$GPRMC开头以换行符’\n’结束的字符串:

  /* find "$GPRMC" from raw_buf */

  if ((wellhandled_string = strstr(raw_buf, “$GPRMC”)) != NULL)

  {

  for (i=0; i<strlen(wellhandled_string); i++)

  {

  if (wellhandled_string == '\n')

  {

  wellhandled_string = '\0'; //replace ‘\n’ with null

  }

  }

  }

  strstr()函数的原型是这样声明的:

  char *strstr(const char *haystack, const char *needle);

  strstr()函数可以在字符串haystack中搜索字符串needle第一次出现的位置,并且返回指向字符串needle首地址的指针,如果没有搜索到则返回NULL。因此上面的代码为我们在读取的原始数据raw_buf里搜索$GPRMC第一次出现的位置,并将返回的指针赋给wellhandled_string,这样如果搜索成功,则wellhandled_string就会指向以$GPRMC开始的字符串,接下来通过一个for循环找到换行符’\n’,将其替换为’\0’,即字符串结束符。这样就得到了一个指向有效数据的字符串指针wellhandled_string。

  然后要做的工作就是从wellhandled_string中提取出经纬度、日期时间等信息。这个工作就可以交给强大的sscanf函数来实现。sscanf函数的原型如下:

  int sscanf(const char *str, const char *format, ...);

  我们都比较熟悉scanf这个函数,scanf可以从标准输入流读取与指定格式相符的数据。sscanf则是从const char *str中读取。它的强大之处在于可以方便地从字符串中取出整数、浮点数和字符串等各种类型的数据,而且它还具有类似于正则表达式的匹配功能,sscanf默认是以空格分隔字符串的,如果不是以空格来分割的话,就可以使用%[ ]来指定分割的条件。如%[a-z]表示读取a到z的所有字符,%[^a-z]表示过滤a-z之间的所有字符,即只要遇到a到z之间的任意字符,转换立刻停止。比如:

  sscanf(“abcdefABCDEF”, “%[^A-Z]”, str);

  printf(“%s\n”, str);

  result is: abcdef

  %[^A-Z]这样的匹配格式为我们取遇到大写字母为止的字符串。利用这种匹配方式,我们就可以灵活的操作字符串,得到我们想要的结果。

  现在我们需要从下面的字符串中提取有效信息:

  $GPRMC,121252.000,A,3958.3032,N,11629.*6,E,15.15,359.95,070306,,,A*54

  GPRMC每个字段的含义如下:

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

  <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~9九条信息。用一个结构体存放这些信息:

  typedef struct gps_info

  {

  char utc_time[BUF_SIZE];

  char status;

  float latitude_value;

  char latitude;

  float longtitude_value;

  char longtitude;

  float speed;

  float azimuth_angle;

  char utc_data[BUF_SIZE];

  }GPS_INFO;

  因为每一个字段之间都是以逗号间隔开的,所以我们可以利用%[^,]来分割字符串,这样用sscanf函数就可以实现对有效信息的提取:

  sscanf(wellhandled_string,"$GPRMC,%[^,],%c,%f,%c,%f,%c,%f,%f,%[^,]",

  rmc_info->utc_time,\

  &(rmc_info->status),&(rmc_info->latitude_value),&(rmc_info->latitude),\

  &(rmc_info->longtitude_value),&(rmc_info->longtitude),&(rmc_info->speed),\

  &(rmc_info->azimuth_angle),\

  rmc_info->utc_data );

  这个函数执行后,打印出的保存在struct gps_info结构体里的信息如下所示:

  utc_time: 024813.640

  status: A

  latitude: N latitude value: 3158.460693

  longtitude: E longtitude value: 11848.374023

  speed: 10.050000

  azimuth_angle: 324.269989

  utc_data: 150706

  可见,利用好sscanf函数,可以让我们可以很高效的处理字符串。

  “本文由华清远见http://www.embedu.org/index.htm提供”

阿莫论坛20周年了!感谢大家的支持与爱护!!

阿莫论坛才是最爱国的,关心国家的经济、社会的发展、担心国家被别国牵连卷入战争、知道珍惜来之不易的和平发展,知道师夷之长,关注世界的先进文化与技术,也探讨中国文化的博大精深,也懂得警惕民粹主义的祸国殃民等等等等,无不是爱国忧民的表现。(坛友:tianxian)

出10入0汤圆

发表于 2010-9-6 21:30:15 | 显示全部楼层
好贴,受教了

出0入0汤圆

发表于 2010-9-6 23:01:21 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-9-12 01:50:03 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-12 06:18:12 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-9-15 18:29:39 | 显示全部楼层
Mark

出0入0汤圆

发表于 2010-9-15 18:33:14 | 显示全部楼层
马克

出0入0汤圆

发表于 2010-9-15 20:23:18 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-15 21:07:31 | 显示全部楼层
标记下,谢谢楼主。

出0入0汤圆

发表于 2010-9-27 09:23:21 | 显示全部楼层
非常精彩!

出0入0汤圆

发表于 2010-9-27 10:30:29 | 显示全部楼层
mark

出0入22汤圆

发表于 2010-9-27 11:17:54 | 显示全部楼层
很好~~

出0入0汤圆

发表于 2010-9-27 11:38:52 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-27 12:16:27 | 显示全部楼层
这个思路好 mark了

出0入170汤圆

发表于 2010-9-27 19:31:07 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-30 10:39:45 | 显示全部楼层
好东西 受教了…………

出0入0汤圆

发表于 2010-9-30 10:59:56 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-2 02:19:31 | 显示全部楼层
非常简明

出0入0汤圆

发表于 2010-10-12 11:17:32 | 显示全部楼层
学习!!

出0入0汤圆

发表于 2010-10-12 11:20:57 | 显示全部楼层
sscanf 高效个P....PC机上罢了,8位机上开销太大

出0入134汤圆

发表于 2010-10-12 11:33:06 | 显示全部楼层
真简洁

出0入0汤圆

发表于 2010-10-12 13:26:46 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 2010-10-12 13:47:49 | 显示全部楼层
回【19楼】 snoopyzz
我是在arm上使用这个函数,一般不必考虑这个问题,当有效率需求时可以自己写个专用函数解决这个问题,这只是其中一个方法而已。
有时候我们考虑跟多的是可读性与通用性。

出0入0汤圆

发表于 2010-10-12 14:59:53 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-10-18 07:13:19 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-18 07:47:53 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-18 09:58:23 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-18 10:20:06 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-18 10:54:29 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-18 17:30:47 | 显示全部楼层
M

出0入0汤圆

发表于 2010-10-25 11:56:16 | 显示全部楼层
不错

出0入0汤圆

发表于 2010-11-1 14:32:22 | 显示全部楼层
这种解析方法,在遇到数据不完整时候会崩溃,有没有更好的解析方法?

出0入0汤圆

发表于 2010-11-1 14:37:35 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-1 15:43:32 | 显示全部楼层
留个脚印。以后好找。

出0入0汤圆

发表于 2010-11-19 10:37:10 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-19 20:28:54 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-23 16:37:59 | 显示全部楼层
我是先开辟一个大的缓冲区,接收完GPS发过来的数据后超时判断再处理数据,自己写了个查找字符串的函数....

出0入0汤圆

发表于 2011-1-26 14:16:20 | 显示全部楼层
mark,转载:如何利用strstr和sscanf解析GPS信息

出0入0汤圆

发表于 2011-2-10 12:34:42 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-2-14 16:30:39 | 显示全部楼层
Mark

出0入0汤圆

发表于 2011-2-14 16:43:47 | 显示全部楼层
我的方法是找字符"R"

因为整个GPS信息中,只有GPRMC才有“R”,其它地方都没有。。。

出0入0汤圆

发表于 2011-2-14 16:52:39 | 显示全部楼层
INT16U Find_Str(INT8U *str, INT8U *ptr)
{
INT16U index = 0;
INT8U *s_temp;        
INT8U *m_temp;        
INT8U *t_temp;  
     
if(str == 0 || ptr == 0)  
    return 0;
for(s_temp = str; *s_temp != '\0'; s_temp++)
{
index++;
m_temp = s_temp;
for(t_temp = ptr; *t_temp == *m_temp; t_temp++, m_temp++){  };
if(*t_temp == '\0')  
return index;
}
return 0;
}
我改写的字符串比较函数,直接在缓冲区内查找“GPRMC",返回偏移量,提取其它的GPS数据也一样

出0入0汤圆

发表于 2011-2-14 16:59:19 | 显示全部楼层
memset(&GPS_GSV_Data, 0x00, sizeof(GPS_GSV_Data));  // 每次处理前将结构体清零   
    index = Find_Str(Uart1_RcvBuf, "$GPGSV,");
    if(index)
    {
        ....
    }

    这样就行了,另外如19楼snoopyzz所说....我也基本不用printf....

出0入0汤圆

发表于 2011-2-14 17:07:12 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-2-14 20:45:38 | 显示全部楼层
回复【41楼】amazing030
-----------------------------------------------------------------------

愣是没看懂,望稍微解释一下,看见指针就晕的人....

出0入0汤圆

发表于 2011-2-15 08:50:13 | 显示全部楼层
for(s_temp = str; *s_temp != '\0'; s_temp++)  // 遍历所查找的字符串
{  
    index++;              // 当前偏移量递增
    m_temp = s_temp;      // 指向当前字符串指针
    for(t_temp = ptr; *t_temp == *m_temp; t_temp++, m_temp++){  };   // 逐个比较当前字符串指针后的字符是否与要比较
                                                                     // 的字符串相同
    if(*t_temp == '\0')   // 如果该指针为空字符则说明上面已比较完而且都相同
        return index;     // 此时返回偏移量index
}  
return 0;

出0入0汤圆

发表于 2011-2-28 22:51:58 | 显示全部楼层
好,正好在ST上刚好用到。

出0入0汤圆

发表于 2011-3-1 13:27:47 | 显示全部楼层
扫描回复【40楼】fsclub  绿林好汉
我的方法是找字符"r"
因为整个gps信息中,只有gprmc才有“r”,其它地方都没有。。。
-----------------------------------------------------------------------

我也是查找GPRMC信息,C3-370模块,因为其中只有这里会出现‘C’,所以扫描到‘C’才开始将数据装入缓冲区。

GPRMC信息格式非常规整,所以用结构体去筛选信息:

struct GPS_INFO{                              
                    unsigned char NOTE0;            
                    unsigned char TIME[10];             //时间
                    
                    unsigned char NOTE1;
                    unsigned char DAV;                  //信息有效
                    
                    unsigned char NOTE2;
                    unsigned char Latitude[9];          //纬度      
                    
                    unsigned char NOTE3;
                    unsigned char NS;                   //NS标识
                          
                    unsigned char NOTE4;
                    unsigned char Longitude[10];        //经度
                    
                    unsigned char NOTE5;
                    unsigned char EW;                   //EW标识
                    
                    unsigned char NOTE6;     //-------------------------
                    unsigned char SPD[4];               //速度

                    unsigned char NOTE7;
                    unsigned char DIR[6];               //速度
                    
                    unsigned char NOTE8;
                    unsigned char DATE[6];               //时间         
                    
                    unsigned char OTH[71];              //其他
               };


union GPS_DATA{            
                    unsigned char rx_buffer1[RX_BUFFER_SIZE1];
                    struct GPS_INFO GI;
                };
               
union GPS_DATA RCV;

如果DAV=‘A’表示坐标信息有效,否则丢弃。

串口接收数据就非常简单了,查找'C'开头的信息,然后话开始接收数据,最后检查到星号'*'时结束,就让主程序处理了:

unsigned char rx_wr_index1;
bit start,end;

interrupt [USART1_RXC] void usart1_rx_isr(void)
    {
        char status,data;
        status=UCSR1A;
        data=UDR1;
        if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
            {   
                if(data=='C')
                    {
                        start=1;  
                        rx_wr_index1=0x00;
                        return;
                    }  
                if((start==1)&&(data=='*'))
                    {
                        start=0;
                        end=1;
                        return;
                    }
                if(start==1)
                    {
                        RCV.rx_buffer1[rx_wr_index1]=data;
                        rx_wr_index1++;
                        return;
                    }
            }
    }

标志位end=1时表示收到了一串完整的GPRMC信息,然后在主程序中读取GPS_DATA共用体中成员的数据即可。

出0入0汤圆

发表于 2011-3-1 14:14:17 | 显示全部楼层
回复【47楼】XA144F
-----------------------------------------------------------------------

不错,受教了!!

出0入0汤圆

发表于 2011-3-3 14:10:01 | 显示全部楼层
回复【47楼】XA144F
扫描回复【40楼】fsclub  绿林好汉
我的方法是找字符"r"
因为整个gps信息中,只有gprmc才有“r”,其它地方都没有。。。
-----------------------------------------------------------------------
我也是查找gprmc信息,c3-370模块,因为其中只有这里会出现‘c’,所以扫描到‘c’才开始将数据装入缓冲区。
gprmc信息格式非常规整,所以用结构体去筛选信息:
struct gps_info{                                
                    unsigned char note0;            
                    unsigned char time[10];             //时间
   ......
-----------------------------------------------------------------------

我收到'R'之后就连存50个收到字符进BUFFER,然后读特定位是不是“A”,是的话定位成功。要什么就用指针去BUFFER读什么。

出0入0汤圆

发表于 2011-3-3 14:18:24 | 显示全部楼层
回复【49楼】fsclub  绿林好汉
-----------------------------------------------------------------------
我的也一样啊,在主程序中,判断RCV.GI.DAV的值是V还是A就行了。

出0入0汤圆

发表于 2011-3-9 21:03:58 | 显示全部楼层
请教楼上几位,我将NEMA语句过滤成功后得到"RMC,063610.000,A,2421.7385,N,10233.3632,E,0.00,,170810,,,A*76"这样的语句,请教如何将其赋值给结构体呢?我使用for语句分段循环赋值,结果很不理想.谢谢.我写的程序如下.
#include <stc12c5a60s2.h>
#include <uinit5a60.h>  
#include <stdio.h>
#include <stdlib.h>
#include "N5110.h"
#define        delay_time        25767       
#define uchar unsigned char
#define uint unsigned int
unsigned char flag,counter,mark=0,a;
uchar xdata cache[100];
void main()
{
        uchar time[11];
        uchar weidu[9];
        uchar jingdu[12];
        uchar i=0,c,h,e;
        LCD_init(); //初始化液晶   
        LCD_clear();
        uinit();
        while(1)
        {

                if(flag==1&counter==1&mark==0)
                {
                        flag=0;
                        cache=SBUF;                         
                        i++;
                }
                if(mark==1)
                {
                        mark=0;
                        h=0;
                         i=0;
                        ES=0;
                for(c=4;c<15;c++)
                        {
                                time[h]=cache[c];
                                h++;
                        }
                        h=0;
                for(c=17;c<26;c++)
                        {
                                weidu[h]=cache[c];
                                h++;
                        }
                        h=0;
                for(c=28;c<40;c++)
                        {
                                jingdu[h]=cache[c];
                                h++;
                        }
                        h=0;
//从此往下为串口输出

                for(e=0;e<11;e++)
                        {
                                SBUF=time[e];
                                while(!TI);
                                TI=0;
                        }
                                SBUF=0x0a;
                                while(!TI);
                                TI=0;
                for(e=0;e<9;e++)
                        {
                                SBUF=weidu[e];
                                while(!TI);
                                TI=0;
                        }
                                SBUF=0x0a;
                                while(!TI);
                                TI=0;                                               
                for(e=0;e<12;e++)
                        {
                                SBUF=jingdu[e];
                                while(!TI);
                                TI=0;
                        }                                       
                                SBUF=0x0a;
                                while(!TI);
                                TI=0;
                                ES=1;
//                LCD_write_english_string(0,0,"GPS ");
                //LCD_clear();
                LCD_write_english_string(0,0,time);//输出time到5110
//                LCD_write_english_string(0,2,"N");
//                LCD_write_english_string(0,3,"L");
//                LCD_write_english_string(1,4,"______________");
//                LCD_write_english_string(1,5,"123ABE");
                               
                }
        }

}

void ser() interrupt 4
{
        RI=0;
        a=SBUF;
        flag=1;
        if(a==0x52) //过滤R
        {
                counter=1;
        }
        if(counter==1&a==0x0a)
        {
                counter=0;
                mark=1;
        }
}
我将time值输出到5110液晶上,有一些乱码,而且从乱码当中竟然可以看到很多不应该有的值,比如",E,0.00,,170810,,,A*76 "都显示出来,但是time的长度最多只有10啊!?.如果在液晶上输出"jingdu"却又是正常的,如果输出"weidu"也乱码,真是百思不得其解.
在串口输出的结果为
063610.000,2421.7385,10233.3632,
063610.000,2421.7385,10233.3632,
063610.000,2421.7385,10233.3632,
063610.000,2421.7385,10233.3632,
很奇怪,这三个值之间的换行符没有了
真是不知道为什么,我甚至怀疑我的程序是不是到处是错误.


.............................................................分割线...........................................................
后来发现问题出'\0'上,由于我没有将逗号换成\0,导致5110的驱动不断将指针加1,当超过数组的边界后就全是乱码了.顺便请教\0的十六进制是0x0a吗?

出0入0汤圆

发表于 2011-3-10 08:39:51 | 显示全部楼层
51L:在串口接收字符的中断里就要对结构体字符串赋值,但前提是要找到开始。我用的结构体中NOTEx表示的是字符串中存在的逗号。

出0入0汤圆

发表于 2011-3-10 17:22:01 | 显示全部楼层
当信息不完整的时候,这样提取数据好像不理想啊
比如GPS还没定位的时候,输出都是一串逗号,没数据

出0入0汤圆

发表于 2011-3-10 18:42:06 | 显示全部楼层
回复【52楼】XA144F
-----------------------------------------------------------------------
请问用什么函数能对结构体整体赋值呢?比如对你的这个结构体赋值,难道要一个个赋值吗?不可以直接将过滤出来的RMC语句整体赋给结构体吗?谢谢.
struct GPS_INFO{                                
                    unsigned char NOTE0;            
                    unsigned char TIME[10];             //时间
                     
                    unsigned char NOTE1;
                    unsigned char DAV;                  //信息有效
                     
                    unsigned char NOTE2;
                    unsigned char Latitude[9];          //纬度      
                     
                    unsigned char NOTE3;
                    unsigned char NS;                   //NS标识
                           
                    unsigned char NOTE4;
                    unsigned char Longitude[10];        //经度
                     
                    unsigned char NOTE5;
                    unsigned char EW;                   //EW标识
                     
                    unsigned char NOTE6;     //-------------------------
                    unsigned char SPD[4];               //速度

                    unsigned char NOTE7;
                    unsigned char DIR[6];               //速度
                     
                    unsigned char NOTE8;
                    unsigned char DATE[6];               //时间           
                     
                    unsigned char OTH[71];              //其他
               };

出0入0汤圆

发表于 2011-3-11 10:11:08 | 显示全部楼层
54L:看清楚:我是用了共用体:

union GPS_DATA{            
                    unsigned char rx_buffer1[RX_BUFFER_SIZE1];
                    struct GPS_INFO GI;
                };
               
union GPS_DATA RCV;

就像压面条一样,面团(rx_buffer1[])压入机器(共用体)之后,出来的是一根根的面条(结构体中的数据)。

出0入0汤圆

发表于 2011-3-14 12:57:51 | 显示全部楼层
这是我的解析函数
typedef struct  
{  
    INT8U Block;  
    INT8U BlockIndex;  
    INT8U UTCTime[10];      // hhmmss.mmm  
    INT8U Status;           // A- 有效定位 V-无效定位  
    INT8U Latitude[9];      // ddmm.mmmm  
    INT8U NS;               // N/S  
    INT8U Longitude[10];    // dddmm.mmmm  
    INT8U EW;               // E/W  
    INT8U Speed[5];         // 速率000.0~999.9节  
    INT8U Course[5];        // 航向000.0~359.9度  
    INT8U UTCDate[6];       // ddmmyy  
}stru_GPSRMC;
INT8U GPRMC_Receive(void)
{
    INT8U buf[13];
    INT8U sbuf;
    INT8U *ptr;
    INT16U index;

    memset(&GPS_RMC_Data, 0x00, sizeof(GPS_RMC_Data));  // 每次处理前将结构体清零
    index = Find_Str(Uart1_RcvBuf, "$GPRMC,");
    if(index)
    {
        ptr = Uart1_RcvBuf  + index + 6;
        do
        {
            sbuf = *ptr++;
            switch(sbuf)
            {
                case ',':       // 接收到数据段分隔符','                             
                    GPS_RMC_Data.Block++;                   // 数据段标志
                    GPS_RMC_Data.BlockIndex = 0;            // 数据段数据计数指针
                    break;  
                default:        // 接收到数据
                    switch(GPS_RMC_Data.Block)  
                    {  
                        case 0:  GPS_RMC_Data.UTCTime[GPS_RMC_Data.BlockIndex] = sbuf;  break;  
                        case 1:  GPS_RMC_Data.Status = sbuf;                            break;  
                        case 2:  GPS_RMC_Data.Latitude[GPS_RMC_Data.BlockIndex] = sbuf; break;  
                        case 3:  GPS_RMC_Data.NS = sbuf;                                break;  
                        case 4:  GPS_RMC_Data.Longitude[GPS_RMC_Data.BlockIndex] = sbuf;break;  
                        case 5:  GPS_RMC_Data.EW = sbuf;                                break;
                        case 6:  GPS_RMC_Data.Speed[GPS_RMC_Data.BlockIndex] = sbuf;    break;  
                        case 7:  GPS_RMC_Data.Course[GPS_RMC_Data.BlockIndex] = sbuf;   break;  
                        case 8:  GPS_RMC_Data.UTCDate[GPS_RMC_Data.BlockIndex] = sbuf;  break;  
                        default: break;
                    }         
                    GPS_RMC_Data.BlockIndex++;  
                    break;
            }
        }while(sbuf != '*');

        memset(buf, 0x00, sizeof(buf));
        buf[0] = GPS_RMC_Data.NS;  
        buf[1] = ' ';
        buf[2] = ' ';
        memcpy(buf + 3, &GPS_RMC_Data.Latitude, 9);
        LCD_ShowString(8, 20, buf, 0);

        memset(buf, 0x00, sizeof(buf));
        buf[0] = GPS_RMC_Data.EW;
        buf[1] = ' ';
        memcpy(buf + 2, &GPS_RMC_Data.Longitude, 10);
        LCD_ShowString(120, 20, buf, 0);

        memset(buf, 0x00, sizeof(buf));
        buf[0] = 'T';
        buf[1] = ' ';
        memcpy(buf + 2, &GPS_RMC_Data.UTCTime, 10);
        LCD_ShowString(8, 40, buf, 0);
/*
        memset(buf, 0x00, sizeof(buf));
        buf[0] = 'S';
        buf[1] = ' ';
        memcpy(buf + 2, &GPS_RMC_Data.Speed, 5);
        LCD_ShowString(8,100, buf, 0);

        memset(buf, 0x00, sizeof(buf));
        buf[0] = 'C';
        buf[1] = ' ';
        memcpy(buf + 2, &GPS_RMC_Data.Course, 5);
        LCD_ShowString(8,120, buf, 0);
*/
    }
    return 0;
}

出0入0汤圆

发表于 2011-3-15 15:53:29 | 显示全部楼层
...

出0入0汤圆

发表于 2011-3-20 10:31:02 | 显示全部楼层
mark,转载:如何利用strstr和sscanf解析GPS信息

出0入0汤圆

发表于 2011-3-21 20:13:05 | 显示全部楼层
mark  mark  mark
有没有人英飞凌C166的板子做过GPS

出0入0汤圆

发表于 2011-3-25 22:27:44 | 显示全部楼层
C语言的好东东 杰西GPS

出0入0汤圆

发表于 2011-4-11 16:26:37 | 显示全部楼层
太好了。。。

出0入0汤圆

发表于 2011-4-12 09:00:05 | 显示全部楼层
C语言的好东东,学习了!

出0入0汤圆

发表于 2011-4-12 09:10:11 | 显示全部楼层
好,太好了~~~

出0入0汤圆

发表于 2011-4-28 00:47:02 | 显示全部楼层
学习

出0入0汤圆

发表于 2011-5-18 09:48:59 | 显示全部楼层
仔细看看。

出0入0汤圆

发表于 2011-5-18 12:59:31 | 显示全部楼层
标记

出0入0汤圆

发表于 2011-5-23 14:37:55 | 显示全部楼层
灰常好!

出0入0汤圆

发表于 2011-6-8 00:16:17 | 显示全部楼层
mark,

出0入0汤圆

发表于 2011-7-13 14:43:53 | 显示全部楼层
标记下  慢慢看

出0入0汤圆

发表于 2011-7-19 15:40:19 | 显示全部楼层
好方法,标记下,留着以后用。不过在不支持浮点运算的CPU里还是尽量避免浮点的好

出0入0汤圆

发表于 2012-2-4 23:31:08 | 显示全部楼层
这里是GPS数据算法学习的一贴。

出0入0汤圆

发表于 2012-6-6 16:11:32 | 显示全部楼层
mark,如何利用strstr和sscanf解析GPS信息

出0入0汤圆

发表于 2012-8-28 20:39:32 | 显示全部楼层
学习一下

出0入0汤圆

发表于 2012-11-12 16:00:34 | 显示全部楼层
马克,好资料  学习了!

出0入0汤圆

发表于 2013-2-20 22:46:42 | 显示全部楼层
好贴!!!!!

出0入0汤圆

发表于 2013-2-21 00:09:27 来自手机 | 显示全部楼层
准备弄GPS协议解释.标记一下.

出0入0汤圆

发表于 2013-3-6 20:49:19 | 显示全部楼层
很好,学习了。

出0入0汤圆

发表于 2013-3-8 14:06:35 | 显示全部楼层
这个还真是处理方便,以前一直用的呆板的处理方法!

出0入0汤圆

发表于 2013-3-8 14:58:03 来自手机 | 显示全部楼层
基本不用printf个scanf家族的函数。我是串口接受数据,扔进fifo,主程序从fifo中读取数据,当读到$时开始往buf中写数据,读到回车时结束,然后校验,正确后将指针传到解析函数中解析。

出0入10汤圆

发表于 2013-10-14 19:29:53 | 显示全部楼层
好贴啊,标记!

出0入0汤圆

发表于 2013-10-14 19:44:22 | 显示全部楼层
guoduan mark

出0入270汤圆

发表于 2014-1-10 18:55:38 | 显示全部楼层
goodsssssss

出0入0汤圆

发表于 2014-6-11 16:06:32 | 显示全部楼层

mark,转载:如何利用strstr和sscanf解析GPS信息,,............好贴,GPS数据算法的精华总结

出0入0汤圆

发表于 2014-6-24 17:49:20 | 显示全部楼层
MARK, 字符串处理函数,sscanf,strstr,解析gps数据

出0入0汤圆

发表于 2015-4-10 22:04:39 | 显示全部楼层
谢谢分享。

出0入0汤圆

发表于 2015-11-19 19:51:12 | 显示全部楼层
学习了  

出0入0汤圆

发表于 2015-11-20 12:01:46 | 显示全部楼层
高手啊!谢谢分享!

出85入85汤圆

发表于 2016-5-27 20:51:15 | 显示全部楼层
必须mark一下。

出0入4汤圆

发表于 2016-5-27 22:21:50 | 显示全部楼层
很详细的解释
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-16 16:44

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表