基於FL2440的GPS模塊開發

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

   系統環境:Centos 6.5

   板子芯片:s3c2440

   內核版本:linux 3.0

      編譯器:arm-linux-gcc 4.5.4

         作者:Lu Zengmeng <[email protected]>

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


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): [email protected]
 *  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): [email protected]
 *  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): [email protected]
 *  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): [email protected]
 *  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>

交叉編譯後下載到開發板上改權限運行即可

發佈了29 篇原創文章 · 獲贊 11 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章