个人陈述信息表:获取GPS模块数据并规格化输出

来源:百度文库 编辑:中财网 时间:2024/04/29 06:29:21
本次做的实验是获取GPS模块的原始数据,并对数据进行规格化处理后再输出,采用单线程方式实现,停止时需要强制中止(按CTRL+C),使用的设备是:瑞泰2410实验箱和HOLUX GR-87的GPS模块,该模块接到箱上的扩展槽上(对应COM1),整个实验过程涉及的步骤是:设置串口1的波特率等参数、读取通过COM1收到的GPS模块返回的原始数据,再进行分离Message ID为$GPRMC的项,并获取该串数据,处理后暂存到相应的数据结构中并输出。实验环境是:ARM+Linux。

    本程序用到的文件有main.c、gps.h、gps.c、Makefile,下面给出源码如下:

    main.c:


#include
#include
#include
#include
#include   
#include "gps.h"

#define BAUDRATE B9600      //串口波特率,即GPS通过COM1发来的数据传输率
#define COM1 "/dev/ttyS1"   //定义与GPS连接的串口1的实际位置,此位置需根据2410箱上的实际来设置

GPS_INFO gps_info;                 //存放分离后的gps数据,是一个结构体,在gps.h中定义
char GPS_BUF[1024];                //存放从串口读到的GPS原始数据
static int baud=BAUDRATE;
volatile int fd;                   //打开串口后保存的设备描述符

void* receive() //当收到一串数据时(以回车符作为分界来识别一串字符),则原样输出,当字符中第6个是C时,则表示是我们需要的数据串(以$GPRMC开头),则对该串进行分离出时间及经纬度并输出来,否则只是原样输出。
{
   int i=0;
   char c;     
   char buf[1024];
   printf("read gps\n");
   while (1)
   {
     read(fd,&c,1);    //从打开的串口COM1(因为GPS模块接到了COM1)读取1个字符
     buf[i++] = c;
     if(c == '\n'){
        strncpy(GPS_BUF,buf,i); //从buf中复制i个字符到GPS_BUF中
        i=0;                    //重置数据的起始位置
        printf("%s",GPS_BUF);   //原样输出
        if(buf[5]=='C'){
            gps_parse(GPS_BUF,&gps_info);  //分离原始数据
            show_gps(&gps_info);           //显示分离后的数据
       }
     }
   }
   printf("exit from reading gps\n");
   return NULL;
}

int main()
{
    struct termios options;         //串口设置的结构
    fd=open(COM1,O_RDWR);
    if (fd <0) {
       perror(COM1);
       exit(-1);
   }
   tcgetattr(fd,&options);
  
    options.c_cflag = baud | CRTSCTS | CS8 | CLOCAL | CREAD;    
    options.c_iflag = IGNPAR;    //忽略奇偶校验
    options.c_oflag = 0;     //Raw 模式输出  //不处理,就原始数据输出
    options.c_lflag = 0; //不处理,原始数据输入  

    options.c_cc[VMIN]=1;     // 阻塞,直到读取到一个字符
    options.c_cc[VTIME]=0;   // 不使用字符间的计时器 
    
    //清空数据线,启动新的串口设置
    tcflush(fd, TCIFLUSH);   //刷新输入队列
    tcsetattr(fd,TCSANOW,&options);            //新属性设置生效
    if(receive()==NULL) exit(-1);调用接收函数收取GPS获到的数据
    exit(0);
}

    gps.h:

#ifndef _GPS_H
#define _GPS_H

typedef struct{
   int year;    //年
   int month;   //月
   int day;     //日
   int hour;    //时
   int minute;  //分
   int second;  //秒
}date_time;  //时间结构体

typedef struct{
    date_time D;//时间
    double latitude;   //纬度
    double longitude;  //经度
    char NS;           //南北极
    char EW;           //东西
}GPS_INFO;

void gps_parse(char *line,GPS_INFO *GPS);
void show_gps(GPS_INFO *GPS);
#endif

   gps.c:

#include
#include
#include
#include
#include "gps.h"

static int GetComma(int num,char* str);       //获得str字符指针对应字符串中第num个逗号的位置
static void UTC2BTC(date_time *GPS);          //将GPS获得的UTC时间转换成北京时间
static double get_double_number(char *s);     //获得两个逗号中间的浮点数,并转成double值返回

void show_gps(GPS_INFO *GPS)//输出GPS分离原始数据后的可用数据(包含时间及经纬度)
{
   printf("DATE     : %ld-%02d-%02d \n",GPS->D.year,GPS->D.month,GPS->D.day);
   printf("TIME     %02d:%02d:%02d \n",GPS->D.hour,GPS->D.minute,GPS->D.second);
   printf("Latitude : %10.4f %c\n",GPS->latitude,GPS->NS); 
   printf("Longitude: %10.4f %c\n",GPS->longitude,GPS->EW); 
}

////////////////////////////////////////////////////////////////////////////////
//解释gps发出的数据
//0       4 6      6 8 0        90                    
//$GPRMC,091400,A,3958.9870,N,11620.3278,E,000.0,000.0,120302,005.6,W*62  
void gps_parse(char *line,GPS_INFO *GPS)
{
   int tmp;
   char c;
   char* buf=line;
   c=buf[5];
   if(c=='C'){//"GPRMC"
      GPS->D.hour   =(buf[ 7]-'0')*10+(buf[ 8]-'0');    //原始数据串中第7位(从0计起)为时钟的十位,而8为个位
      GPS->D.minute =(buf[ 9]-'0')*10+(buf[10]-'0');    //                           分钟          10
      GPS->D.second =(buf[11]-'0')*10+(buf[12]-'0');    //              11              秒钟          12

      tmp = GetComma(9,buf);              //获得buf中第9个逗号的起始位置,即在数据buf中的下标
      GPS->D.day    =(buf[tmp+0]-'0')*10+(buf[tmp+1]-'0');        
      GPS->D.month  =(buf[tmp+2]-'0')*10+(buf[tmp+3]-'0');
      GPS->D.year   =(buf[tmp+4]-'0')*10+(buf[tmp+5]-'0')+2000;

      GPS->latitude =get_double_number(&buf[GetComma(3,buf)]);      //纬度
      GPS->NS       =buf[GetComma(4,buf)];                          //南s北n
      GPS->longitude=get_double_number(&buf[GetComma(5,buf)]);      //经度
      GPS->EW       =buf[GetComma(6,buf)];                          //东e西w
      UTC2BTC(&GPS->D);
   }
}

//获得在字符串s中第一个逗号前的数值,并转换为浮点数返回
static double 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; 
}
//返回str中第num个逗号的下一位置(从0起)
static int GetComma(int num,char *str)
{
  int i,j=0;
  int len=strlen(str);
  for(i=0;i  {
     if(str[i]==',')j++;
     if(j==num)return i+1; 
  }
  return 0; 
}
//将世界时转换为北京时
static void UTC2BTC(date_time *GPS)
{
   //如果秒号先出,再出时间数据,则将时间数据+1秒
   GPS->second++; //加一秒
   if(GPS->second>59){
      GPS->second=0;
      GPS->minute++;
      if(GPS->minute>59){
        GPS->minute=0;
        GPS->hour++;
      }
  
  GPS->hour+=8;   //北京时间与世界时间相差8个时区,即相差8个钟
  if(GPS->hour>23)
  {
     GPS->hour-=24;
     GPS->day+=1;
     if(GPS->month==2 || GPS->month==4 || GPS->month==6 || GPS->month==9 || GPS->month==11 ){
        if(GPS->day>30){
           GPS->day=1;
           GPS->month++;
        }
     }
     else{
        if(GPS->day>31){
           GPS->day=1;
           GPS->month++;
        }
   }
   if((GPS->year % 4 ==0) && (GPS->year % 400 == 0 || GPS->year % 100 != 0)){  //判断闰年
       if(GPS->day > 29 && GPS->month ==2){   //闰年二月比平年二月多一天
          GPS->day=1;
          GPS->month++;
       }
   }
   else{
       if(GPS->day>28 &&GPS->month ==2){
         GPS->day=1;
         GPS->month++;
       }
   }
   if(GPS->month>12){
      GPS->month-=12;
      GPS->year++;
    
  }
}
   Makefile:

EXEC =  gps    #最终的可执行目标文件名
OBJS =  main.o gps.o    #编译过程中需要用到的对象,如果没有规格生成.o文件,make工具会先自动生成
CC = /home/guochongxin/crosstool/gcc-4.1.0-glibc-2.3.2/arm-9tdmi-linux-gnu/bin/arm-9tdmi-linux-gnu-gcc   #设置交叉编译工具链的位置

all: $(EXEC)


$(EXEC): $(OBJS)
       $(CC) -o $@ $(OBJS)  #$@相当于$(EXEC)   该行前面的按Tab键空出来的

clean: 
       -rm -f $(EXEC) *.o   #移除时是删除目标文件及中间生成的.o文件  该行前面的按Tab键空出来的
    本程序只是单线程的通过串口获取GPS数据并规格化数据后输出需要的数据,通过本实验可以为获到有效数据提供有利的前提。