學(xué)習(xí)啦 > 學(xué)習(xí)電腦 > 操作系統(tǒng) > Linux教程 > Linux下接收處理GPS數(shù)據(jù)教程

Linux下接收處理GPS數(shù)據(jù)教程

時間: 志藝942 分享

Linux下接收處理GPS數(shù)據(jù)教程

  Linux的性能、可靠性、靈活性、和開放性,與其支持多微處理器體系結(jié)構(gòu)、硬件設(shè)備、圖形支持和通信協(xié)議相結(jié)合,把Linux建成了一個日益發(fā)展的操作系統(tǒng)平臺。接下來是小編為大家收集的Linux下接收處理GPS數(shù)據(jù)教程,希望能幫到大家。

  Linux下接收處理GPS數(shù)據(jù)教程

  1,接收數(shù)據(jù)

  這個名字有點籠統(tǒng),確切講是串口接收gps模塊的原始數(shù)據(jù),在fl2440開發(fā)板左側(cè)大家可以看到有兩個母頭串口(如圖1)

  在開發(fā)板上 ls /dev 你會發(fā)現(xiàn)

  ttyS0(這個是連接到電腦的串口,也是圖一中上面的那個串口),

  ttyS1(這個就是圖一中下面的串口,也是連接gps模塊,我們需要監(jiān)聽的串口)

  由于gps模塊也是母頭,所以需要自己制作一個公頭線,首先進行硬件上的聯(lián)通,下面看一下RS_232的db9線每一個引腳的作用

  --------------下圖為引腳順序圖------------

  Db9中有效的通信引腳2(RXD),3(TXD),5(GND)。在公頭和母頭進行連接時,公頭2連接母頭3,公頭3連接母頭2。5接5。這樣硬件實現(xiàn)了連接。如下,

  gps模塊接上電,此時可以監(jiān)聽串口了,

  監(jiān)聽串口命令 microcom -s 4800 /dev/ttyS1

  有了上述結(jié)果。說明接收數(shù)據(jù)是可以實現(xiàn)的??吹竭@里不知道有沒有人有疑問,這樣就可以直接收到數(shù)據(jù)么,gps,串口都是設(shè)備,不需要對gps和串口進行驅(qū)動使能么?是這樣的,在一開始內(nèi)核中就已經(jīng)對串口驅(qū)動進行了使能,而gps模塊中有g(shù)ps模塊的驅(qū)動,這個模塊通過自身的串口不斷的發(fā)送數(shù)據(jù)開發(fā)板需要做的就是讀取然后處理就夠了,

  以上步驟成功,說明硬件上的連通性沒的問題,可以說只是準(zhǔn)備工作,接下來的才是重點,

  串口編程!!!

  數(shù)據(jù)分析!!!

  重要的事情要說三個感嘆號

  其實編寫GPS數(shù)據(jù)解析程序就是ARM+linux串口編程,串口編程是嵌入式應(yīng)用程序開發(fā)中最基礎(chǔ)也是最重要的部分,如何從一個串口設(shè)備獲取數(shù)據(jù)并將這些數(shù)據(jù)做一定的解析呢?OK,串口編程大致可以分為以下幾個步驟:

  至于串口編程的詳細(xì)介紹,如何設(shè)置波特率,如何設(shè)置停止位等等,以下給出兩個linux串口編程的博客鏈接,講的很詳細(xì)

  http://www.cnblogs.com/wblyuyang/archive/2011/11/21/2257544.html

  http://blog.csdn.net/mtv0312/article/details/6599162

  其中串口設(shè)置其實就相當(dāng)于串口通信的協(xié)議,

  波特率:是為了兩者信號流能同步,

  數(shù)據(jù)位:是指又幾位數(shù)據(jù)封裝成一幀

  結(jié)束位:是指以幀傳輸數(shù)據(jù)時,協(xié)定好結(jié)束位,便于提取有效數(shù)據(jù)

  奇偶校驗:檢驗數(shù)據(jù)的一種手段

  四者的設(shè)置又通信雙方協(xié)定。

  數(shù)據(jù)分析!!!

  $GPRMC,最常用的字符串,包含了時間,日期,定位,和航速航向信息。一般應(yīng)用,只要有這些信息就可以了。

  $GPGGA,包含了定位信息相關(guān)的詳細(xì)信息。如定位時用到的星數(shù),定位的方式,天線的海拔高度,精度等等。

  $GPGSA,包含了定位,水平,海拔三種DOP信息,即精度信息,包含了定位所用到的衛(wèi)星ID。

  $GPGSV,包含了GPS模塊可以看到的星數(shù)(注意,只是能看到的星數(shù),實際使用到的星數(shù)在GPGGA中),以及這些衛(wèi)星的ID號,仰角,方位角,信噪比。關(guān)于這種字符串要特別說明的是,它可能會由幾條GPGSV字符串組成,因此,每個字符串都包含了共幾條字符串,本字串是第幾條這樣的信息。一般的GPS最多是三條。也有的GPS模塊會超過3條。

  $GPVTG,包含了更詳細(xì)的航向航速的信息,航向信息分為以真北為參考和以地磁北為參考(真北和地磁北是不一樣的,兩者相差幾度),航速信息則給出了以節(jié)為單位和以公里/時為單位的數(shù)據(jù)。

  以上信息,一般GPS模塊都會默認(rèn)輸出,也有的模塊只輸出其中幾個。

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

  <1> UTC時間,hhmmss(時分秒)格式

  <2> 定位狀態(tài),A=有效定位,V=無效定位

  <3> 緯度ddmm.mmmm(度分)格式(前面的0也將被傳輸)

  <4> 緯度半球N(北半球)或S(南半球)

  <5> 經(jīng)度dddmm.mmmm(度分)格式(前面的0也將被傳輸)

  <6> 經(jīng)度半球E(東經(jīng))或W(西經(jīng))

  <7> 地面速率(000.0~999.9節(jié),前面的0也將被傳輸)

  <8> 地面航向(000.0~359.9度,以真北為參考基準(zhǔn),前面的0也將被傳輸)

  <9> UTC日期,ddmmyy(日月年)格式

  <10> 磁偏角(000.0~180.0度,前面的0也將被傳輸)

  <11> 磁偏角方向,E(東)或W(西)

  <12> 模式指示(僅NMEA0183 3.00版本輸出,A=自主定位,D=差分,E=估算,N=數(shù)據(jù)無效)

  例如

  $GPRMC,074030.00,A,3941.10576,N,11810.52559,E,0.879,136.15,020210,,,A*64

  UTC時間 定位狀態(tài) 緯度 經(jīng)度 航速 航向 UTC時間/年

  $GPGGA,074030.00,3941.10576,N,11810.52559,E,1,06,11.32,46.6,M,-2.7,M,,*4A

  UTC時間 緯度 經(jīng)度 GPS狀態(tài) 正在使用衛(wèi)星數(shù) 水平精度 海拔高度碼

  基本思路:

  open /dev/ttyS1

  read()讀串口一的數(shù)據(jù)存入到緩存里

  Strstr()在緩存里進行字符串“$GPRMC”的匹配,然后返回匹配的字符串的位置處

  Sscanf()將$GPRMC的有用數(shù)據(jù)另存起來,

  具體代碼如下

  設(shè)置串口

  set_ttyS1.c

  #include <stdio.h>

  #include <string.h>

  #include <errno.h>

  #include <sys/stat.h>

  #include <fcntl.h>

  #include <unistd.h>

  #include <termios.h>

  #include <sys/types.h>

  #include <stdlib.h>

  #include "gpsd.h"

  int 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)

  {

  perror("com set error");

  return -1;

  }

  return 0;

  }

  分析gps數(shù)據(jù)函數(shù)

  analysis.c

  #include <stdio.h>

  #include <string.h>

  #include <stdlib.h>

  #include <sys/types.h>

  #include <errno.h>

  #include <sys/stat.h>

  #include <fcntl.h>

  #include "gpsd.h"

  int gprmc_analysis (char *buff,GPRMC *gprmc)

  {

  char *ptr = NULL;

  if(gprmc == NULL)

  return -1;

  if(strlen(buff) < 10)

  return -1;

  if(NULL == (ptr = strstr(buff,"$GPRMC")))

  return -1;

  sscanf(ptr,"$GPRMC,%d.000,%c,%f,N,%f,E,%f,%f,%d,,,%c*",\

  &(gprmc->time),&(gprmc->pos_state),&(gprmc->latitude),&(gprmc->latitude),&(gprmc->speed),&(gprmc-

  >direction),&(gprmc->date),&(gprmc->mode));

  return 0;

  } /* ----- End of gprmc_analysis() ----- */

  測試函數(shù)

  test.c

  #include <stdio.h>

  #include <string.h>

  #include <sys/types.h>

  #include <errno.h>

  #include <sys/stat.h>

  #include <fcntl.h>

  #include <unistd.h>

  #include <termios.h>

  #include <stdlib.h>

  #include "gpsd.h"

  #define GPS_LEN 512

  int gprmc_analysis (char *buff,GPRMC *gprmc);

  int open_com(char *device_name);

  int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop);

  int main (int argc, char **argv)

  {

  int fd = 0;

  int nread = 0;

  GPRMC gprmc;

  //GPRMC *gprmc;

  char gps_buff[GPS_LEN];

  char *dev_name = "/dev/ttyS1";

  fd = open_com(dev_name);

  set_opt(fd,4800,8,'N',1);

  while(1)

  {

  sleep(2);

  //注意這個時間的設(shè)置,設(shè)置不恰好的話,會導(dǎo)致GPS數(shù)據(jù)讀取不完成,數(shù)據(jù)解析出錯誤

  nread = read(fd,gps_buff,sizeof(gps_buff));

  printf("gps_buff: %s", gps_buff);

  memset(&gprmc, 0 , sizeof(gprmc));

  gprmc_analysis(gps_buff, &gprmc);

  if(nread > 0)

  {

  printf("===========================================\n");

  printf("= GPS狀態(tài)位 : %c [A:有效狀態(tài) V:無效狀態(tài)]==\n" ,gprmc.pos_state);

  printf("= GPS模式位 : %c [A:自主定位 D:差分定位]==\n" , gprmc.mode);

  printf("=日期 : 20%02d-%02d-%02d=\n",gprmc.date%100, (gprmc.date%10000)/100,gprmc.date/10000);

  printf("=時間 : %02d:%02d:%02d=\n",(gprmc.time/10000+8)%24,(gprmc.time%10000)/100,gprmc.time%100);

  printf("=緯度 : 北緯:%.3f=\n",(gprmc.latitude/100));

  printf("=經(jīng)度 : 東經(jīng):%.3f=\n",(gprmc.longitude/100));

  printf("=速度 : %.3f =\n",gprmc.speed);

  printf("===========================================\n");

  }

  }

  close(fd);

  return 0;

  } /* ----- End of main() ----- */

  頭文件

  gpsd.h

  #ifndef __GPSD_H__

  #define __GPSD_H__

  typedef unsigned int UINT;

  typedef int BYTE;

  typedef long int WORD;

  typedef struct __gprmc__

  {

  UINT time; //時間

  char pos_state; //定位狀態(tài)

  float latitude; //緯度

  float longitude; //經(jīng)度

  float speed; //移動速度

  float direction; //方向

  UINT date; //日期

  float declination; //磁偏角

  char dd; //磁偏角方向

  char mode;

  } GPRMC;

  extern int open_com(char *device_name);

  extern int gprmc_analysis(char *buff,GPRMC *gprmc);

  extern int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop);

  #endif

  代碼寫好后如下

  Makefile

  生成的gps可執(zhí)行文件,下載到開發(fā)板上,運行,ok


看了“Linux下接收處理GPS數(shù)據(jù)教程”還想看:

1.數(shù)據(jù)包接收詳解

2.Linux如何對網(wǎng)站數(shù)據(jù)進行自動備份和刪除

3.怎么備份遠(yuǎn)程mysql數(shù)據(jù)庫的腳本文件

2806224