基于FL2440的GPS模块开发

--------------------------------------------------------------------------------------------------------------------------------

   系统环境:Centos 6.5

   板子芯片:s3c2440

   内核版本:linux 3.0

      编译器:arm-linux-gcc 4.5.4

         作者:Lu Zengmeng <1540999272@qq.com>

--------------------------------------------------------------------------------------------------------------------------------


1、GPS简介

全球定位系统(Global Positioning System,通常简称GPS)是一个中距离圆型轨道卫星导航系统。它可以为地球表面绝大部分地区(98%)提供准确的定位、测速和高精度的时间标准。系统由美国国防部研制和维护,可满足位于全球任何地方或近地空间的军事用户连续精确的确定三维位置、三维运动和时间的需要。该系统包括太空中的24颗GPS卫星;地面上的1个主控站、3个数据注入站和5个监测站及作为用户端的GPS接收机。最少只需其中4颗卫星,就能迅速确定用户端在地球上所处的位置及海拔高度;所能收联接到的卫星数越多,解码出来的位置就越精确。

该系统是由美国政府于20世纪70年代开始进行研制于1994年全面建成。使用者只需拥有GPS接收机,无需另外付费。GPS信号分为民用的标准定位服务(sps,standard positioning service)和军规的精密定位服务(pss,precise positioning service)两类。民用讯号中加有误差,其最终定位精确度大概在100米左右;军规的精度在十米以下。2000年以后,克林顿政府决定取消对民用信号所加的误差。因此,现在民用GPS也可以达到十米左右的定位精度。

GPS系统拥有如下多种优点:全天候,不受任何天气的影响;全球覆盖(高达98%);三维定速定时高精度;快速、省时、高效率;应用广泛、多功能;可移动定位;不同于双星定位系统,使用过程中接收机不需要发出任何信号增加了隐蔽性,提高了其军事应用效能。

2、GPS模块与开发板的数据传输

GPS模块上电后,会不断往串口发送定位信息,所以只需一根串口线相连,开发板就可以通过串口收到来自GPS模块发送的定位信息。而我们要做的,就是正确配置串口,从串口获取数据并解析出我们所需要的信息即可。

3、GPS数据格式

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

我们只需要对其中的GPRMC(最小定位信息)解析便可获得基本位置信息

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>模式指示(仅NMEA01833.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效)

4、串口配置

通过串口获取GPS数据其实就是串口编程,在嵌入式系统中,串口通信是很基础也很重要的通信方式。对串口的配置可参考博客点击打开链接

下面贴上源代码

头文件

<span style="font-size:14px;">/*************************************************************************
 *  Copyright (C): 1540999272@qq.com
 *  Filename:      serial.h
 *  Author:        Lu Zengmeng
 *  Description:   
 *  Creat Time:    2016-03-06 12:11
 ************************************************************************/

#ifndef __GPS_H__
#define __GPS_H__
extern int speed_arr[];
extern int name_arr[];
extern int nread;
extern int ret;
extern int speed_arr[];
//int gprmc_analysis(char *buff,GPRMC *gprmc);
typedef unsigned int UINT;
typedef struct _gprmc_
{
	UINT         time;
	char         status;
	float        latitude;
	char         latitude_pos;
	float        longitude;
	char         longitude_pos;
	float        speed;
	float        direction;
	UINT         date;
	char         mode;
}GPRMC;


#endif</span>
gps数据解析

<span style="font-size:14px;">/*************************************************************************
 *  Copyright (C): 1540999272@qq.com
 *  Filename:      gps_analysis.c
 *  Author:        Lu Zengmeng
 *  Description:   
 *  Creat Time:    2016-03-06 14:18
 ************************************************************************/
#include<stdio.h>
#include<string.h>
#include"gps.h"

int gprmc_analysis(char *buff,GPRMC *gprmc)
{
	char *ptr = NULL;
	if(NULL==gprmc)
	{
		return -1;
	}

	if(strlen(buff)<2)
	{
		return -1;
	}

	if(NULL==(ptr = strstr(buff,"$GPRMC")))
	{
		return -1;
	}

   	sscanf(ptr,"$GPRMC,%d.000,%c,%f,%c,%f,%c,%f,%f,%d,,,%c*",\
			&(gprmc->time),&(gprmc->status),\
			&(gprmc->latitude),&(gprmc->latitude_pos),\
	        &(gprmc->longitude),&(gprmc->longitude_pos),\
			&(gprmc->speed),&(gprmc->direction),\
			&(gprmc->date),&(gprmc->mode));
	printf("--------------------\n");
	switch (gprmc->status) 
	{
		case 'A':
			printf("有效定位\n");
			break;
		case 'V':
			printf("无效定位\n");
		default:
			return -1;
	}
	switch (gprmc->mode) 
	{
		case 'A':
			printf("自主定位\n");
			break;
		case 'D':
			printf("差分\n");
			break;
		case 'E':
			printf("估算\n");
			break;
		case 'N':
			printf("数据无效\n");
			break;
		default:
			return -1;
	}	

	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,(gprmc->time%10000)/100,gprmc->time%100);

	switch (gprmc->latitude_pos) 
	{
		case 'S':
			printf("南纬:%.2f\n",gprmc->latitude/100);
			break;
		case 'N':
			printf("北纬:%.2f\n",gprmc->latitude/100);
			break;
		default:
			return -1;
	}

	switch (gprmc->longitude_pos) 
	{
		case 'E':
			printf("东经:%.2f\n",gprmc->longitude/100);
			break;
		case 'W':
			printf("西经:%.2f\n",gprmc->longitude/100);
			break;
		default:
			return -1;
	}
	printf("--------------------\n");
	return 0;
}
</span>

串口设置

<span style="font-size:14px;">/*************************************************************************
 *  Copyright (C): 1540999272@qq.com
 *  Filename:      serial_init.c
 *  Author:        Lu Zengmeng
 *  Description:   
 *  Creat Time:    2015-11-28 14:24
 ************************************************************************/
#include<stdio.h>
#include<termios.h>
#include<fcntl.h>
#include<string.h>
#include"gps.h"

#define FAIL -1
#define OK 0
 
int speed_arr[] = {B38400, B19200, B9600, B4800, B2400, B1200, B300,
	B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300,
	38400, 19200, 9600, 4800, 2400, 1200, 300, };

/* set baud rate */
void set_speed(int fd, int speed)
{
	int i;
    int status;
    struct termios options;

    tcgetattr(fd, &options);
    options.c_iflag &= ~ (INLCR | ICRNL | IGNCR);
    options.c_oflag &= ~(ONLCR | OCRNL);
    options.c_iflag &= ~(IXON);
    for( i= 0; i < sizeof(speed_arr) / sizeof(int); i++)
    {
	    if(speed == name_arr[i])
        {
            tcflush(fd, TCIOFLUSH);/*empty input cache*/
            cfsetispeed(&options, speed_arr[i]);
            cfsetospeed(&options, speed_arr[i]);
            status = tcsetattr(fd, TCSANOW, &options);
            if(status != 0)
	           perror("tcsetattr fd");
		    return;
        }
		tcflush(fd,TCIOFLUSH);/*empty input cache*/
	}
}


/**
 * *@brief 设置串口数据位,停止位和效验位
 * *@param fd 类型 int 打开的串口文件描述符
 * *@param databits 类型 int 数据位 取值 为 7 或者8
 * *@param stopbits 类型 int 停止位 取值为 1 或者2
 * *@param parity 类型 int 效验类型 取值为N,E,O,S
 * */
int set_Parity(int fd,int databits,int stopbits,int parity)
{
	    struct termios options;
	    if ( tcgetattr( fd,&options) != 0)
	    {
	        perror("SetupSerial 1");
	        return(FAIL);
	    }
	    options.c_cflag &= ~CSIZE;
	    options.c_lflag  &= ~(ICANON | ECHO | ECHOE | ISIG);  /*Input*/
	    options.c_oflag  &= ~OPOST;   /*Output*/
	    switch (databits) /*set datebits*/
	    {
		    case 7:
				options.c_cflag |= CS7;
				break;
		    case 8:
				options.c_cflag |= CS8;
				break;
	        default:
				fprintf(stderr,"Unsupported data size\n");
				return (FAIL);
	    }
	    switch (parity)
	    {
			case 'n':
			case 'N':
				options.c_cflag &= ~PARENB; /* Clear parity enable */
		        options.c_iflag &= ~INPCK; /* Enable parity checking */
			    break;
			case 'o':
			case 'O':
			    options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
			    options.c_iflag |= INPCK; /* Disnable parity checking */
				break;
			case 'e':
			case 'E':
			    options.c_cflag |= PARENB; /* Enable parity */
			    options.c_cflag &= ~PARODD; /* 转换为偶效验*/
			    options.c_iflag |= INPCK; /* Disnable parity checking */
			    break;
			case 'S':
			case 's': /*as no parity*/
		        options.c_cflag &= ~PARENB;
		        options.c_cflag &= ~CSTOPB;
		        break;
		    default:
		        fprintf(stderr,"Unsupported parity\n");
		        return (FAIL);
		}
		/*set stopbits */
		switch (stopbits)
		{
		    case 1:
		        options.c_cflag &= ~CSTOPB;
		        break;
		    case 2:
		        options.c_cflag |= CSTOPB;
		        break;
		    default:
		        fprintf(stderr,"Unsupported stop bits\n");
		        return (FAIL);
		}
		/* Set input parity options */
		if (parity != 'n')
		    options.c_iflag |= INPCK;
		options.c_cc[VTIME] = 0; // 15 seconds
		options.c_cc[VMIN] = 0;
		tcflush(fd,TCIFLUSH); /* Update the optionsions and do it NOW */
		if (tcsetattr(fd,TCSANOW,&options) != 0)
		{
			perror("tcsetattr");
		    return FAIL;
		}
		return (OK);
}
/**
 * *@breif open device
 * */
int open_dev(char *Dev)
{
    int fd = open( Dev, O_RDWR | O_NOCTTY | O_NDELAY);
		 
    if (-1 == fd)
    {
        perror("open");
        return FAIL;
    }
    else
	    return fd;
				 
}
</span>

主程序

<span style="font-size:14px;">/************************************************************************* *  Copyright (C): 1540999272@qq.com
 *  Filename:      serial_test.c
 *  Author:        Lu Zengmeng
 *  Description:   
 *  Creat Time:    2015-11-28 11:47
 ************************************************************************/
#include <stdio.h>
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <fcntl.h> /*file control definition */  
#include <termios.h>/*terminal control definition*/ 
#include <errno.h> 
#include "gps.h"

#define DEVICE "/dev/ttyS1"
#define BUFF_LEN 1024


/* start main */
int main(int argc,char **argv)
{

	/* open device */
	int    fd;
	char   *dev = DEVICE;
	fd = open_dev(dev);
	printf("打开设备...fd:%d\n",fd);

	/* configure device */
	set_Parity(fd,8,1,'N');
	set_speed(fd,speed_arr[3]);

	GPRMC gprmc;
	char buff[BUFF_LEN];
	int  nread;
	printf("开始定位...\n");

	//while(1)
	int i;
	for(i=0;i<5;i++)
	{
		memset(buff,0,sizeof(buff));
		fcntl(fd, F_SETFL, FNDELAY);
		if((nread=read(fd,buff,sizeof(buff)))<0)
		{
			perror("read");
		}
		sleep(2);
	//fprintf(stdout,"%s,\n",buff);
	
		memset(&gprmc,0,sizeof(gprmc));
		gprmc_analysis(&buff,&gprmc);

	}

	/*close device*/
	close(fd);
	printf("定位结束...\n");
	printf("关闭设备...\n");

	return 0;
}
/* end of main */
</span>

交叉编译后下载到开发板上改权限运行即可

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值