ARM-Linux平台下GPS信号的采集与处理研究
在实际的GPS应用中,并不会用到NMEA的全部信息,而是根据具体的需要,从中选取有用的信息,忽略其余的信息内容。下面以GPRMC语句为例来介绍。该语句包含时间、日期、方位、速度和磁偏角等信息,基本上可以满足一般的导航需求。GPRMC语句的结构为:$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>4 GPS信号的采集和处理
为实现ARM-Linux平台下GPS信号的采集与处理,涉及到Linux下串口编程技术,首先给出Linux串口通信的原理,然后利用多线程编程技术来完成GPS数据采集与NMEA数据格式的解析,因解析后得到的GPS定位坐标属于WGS84坐标,需转换到相应的54、80坐标或地方坐标供用户标图定位所用,因此介绍了一种坐标转换方法。
4.1 GPS数据采集与处理
大多数GPS接收机与各种处理器平台进行数据交换时,都采用异步串行传送方式,提供一个符合RS-232C电气标准的数据接口。
在Linux操作系统中,所有设备以设备文件的形式存储在目录/dev/下,串口设备文件为/dev/ttyS*,在Linux中,若要设置串口的参数,如改变串口的波特率、字符大小等,可通过POSIX标准终端接口[3],该接口被称为termios,在系统头文件中定义。它包括一个数据结构和一系列操纵这些数据结构的函数组成。有关串口的所有参数配置都保存在接口termios的结构struct termios中,该结构定义如下:
struct termios
{
tcflag_t c_iflag; /*输人模式标志*/
tcflag_t c_oflag; /*输出模式标志*/
tcflag_t c_cflag; /*控制模式标志*/
tcflag_t c_lflag; /*本地模式标志*/
cc_t c_cc[NCCS];/*特殊控制字符*/
}
其中的c_iflag成员是用来控制输入处理选项的,它影响到终端驱动程序将输入发送给程序前是否对其进行处理,及怎样对其进行处理。c_oflag成员是用来控制输出数据的处理,并决定在发送输出数据到显示屏和其他输出设备之前,终端驱动程序是否以及如何来处理它们。c_cflag用于存放各种决定终端设备硬件特性的控制标志,如串口的波特率、奇偶校验、停止位、数据位等。存放在c_lflag 中的本地模式标志用来操纵串口如何处理输入字符,比如是否将输入字符显示到显示屏上,一般可通过此成员来设置串口为正规模式或是非正规模式。c_cc数组成员用来定义支持的特殊控制字符以及一些timeout参数。
除了上面的这个包含串口参数配置的数据结构之外,termios中还包含许多控制串口特性的函数。其中重要的几个函数如:tegetattr( )、tesetattr( )、cfsetispeed( )、cfsetospeed( )、tcflush( )。tegetattr( )用来初始化一个termios数据结构,之后可使用其他的函数来操纵由tegetattr( )返回的数据结构。完成这些操作后,使用tesetattr( )来更新串口的设置。cfsetispeed( )用来设置串口的输入速度。cfsetospeed( )用来设置串口的输出速度。tcflush( )用来清除所有队列在串口的输入与输出。
在Linux下采用多线程编程技术可大大节省系统的开销,方便各线程之间通信,提高应用程序的响应,改善程序结构,从而可以提高嵌入式系统的性能。本文就是利用Linux下多线程编程来实现GPS数据的采集和处理,在GPS模块的初始化GPS_Initial函数中创建接收线程GPS_Thread_Port_Svc,在接收线程中调用GPS信息语句的解析函数GPS_Parse_Data(buf_GPS,&gps_data),进一步调用语句字符串解析函数
GPS_Parse_Data_Line(char*str_gprs_data_line,GPS_DATA_TYPE*GPS_DATA)。在GPS语句的处理过程中,需对所读取的语句进行鉴别区分,只选取其中要用的信息进行处理而忽略其余的信息,这就要根据NMEA-0183协议中规定的语句格式来进行解析。图3给出了GPS数据处理流程。
下面是程序实现的关键函数部分代码。
/*包含必要的头文件*/
#include
#include
#include
#include
#include
#include
#include
int GPS_Initial(int n_tty_no)
{
int ret_tty=-1;
int ret_thread=-1;
ret_tty=OpenComPort(n_tty_no,9600,8,"1",‘N’);/*打开串口,并设置通信属性,如波特率,数据位,有无奇偶校验,停止位等*/
ret_thread=pthread_create(&pthr_id,NULL,GPS_
Thread_Port_Svc,NULL);/*创建接收线程*/
…
}
void*GPS_Thread_Port_Svc(void*pData)
{/*接收线程函数*/
unsigned char buf_GPS[256];
int ret_rd_com;
while(1) {
bzero(buf_GPS,sizeof(buf_GPS));
ret_rd_com=ReadComPort((void*)buf_GPS,
sizeof(buf_GPS));/*读串口,接收数据*/
GPS_Parse_Data(buf_GPS,&gps_data);
/*调用解析语句函数,*/
…}
在GPS_Parse_Data(buf_GPS,&gps_data)函数中每接收一个GPS语句,调用一次字符串解析函数。
GPS_Parse_Data_Line(char*str_gprs_data_line,GPS_DATA_TYPE*GPS_DATA){
char*temptr;
temptr=str_gprs_data_line;
/*字符串赋给临时指针,然后对其解析*/
if(strncmp(temptr,RMC_DATA_L,strlen(RMC_DATA_L))==0) {/*解析RMC语句串*/
startchar(temptr,',');
temptr=temptr+strlen(temptr)+12;
/*$GPRMC,HHMMSS.SSS*/
GPS_DATA->Time.Flag=temptr[0];
temptr=temptr+27;
/*A,DDMM.MMMM,N,DDDMM.MMMM,E*/
…}
以上只是GPS信息处理的部分代码。经过交叉编译调试下载至目标平台上,运行后可得到本地地理位置信息。实验所得数据为:时间10:28:35;纬度:北纬30°46’;经度:东经103°57’。用户也可以根据需要选择提取GPS的其他语句,只需编写解析相应语句字符串的代码即可。
4.2 GPS坐标的转换
上述所得的结果属于WGS84坐标,而在工程上实用的大多是国家坐标系,因此GPS数据采集结果的使用就存在与国家坐标系间的坐标转换问题。一般要通过两步转换:首先将上述实测经纬度坐标即WGS84大地坐标(L,B)转换为对应于WGS84椭球的高斯平面坐标(X84,Y84),然后再经过平面坐标转换,将高斯平面坐标(X84,Y84)强制附合到本地高斯平面坐标系统[4]。
(1)高斯投影换算
将GPS采集所得出的大地坐标(L,B)转换为高斯平面坐标(X84,Y84)。有关的推导过程较复杂,本文只给出结果:
由上述原理利用EXCEL就可以算出对应的高斯平面坐标。
(2)平面坐标转换
平面坐标转换的目的就是将高斯投影换算得出平面坐标(X84,Y84)转换为当地国家坐标系的平面坐标。下面介绍一种平均转轴相似转换法,以转换为北京54坐标系下的平面坐标(X54,Y54)为例,说明该方法实现过程。
首先,根据公共点分别在WGS84和北京54系中的高斯平面坐标,求出该点在两个坐标系中同一边的方位角之差?驻?琢和长度比例系数?资,然后按下式计算任一点在北京54系中的平面坐标。
- 基于MCU的机器人导航定位系统设计(10-22)
- 基于GPS和GPRS的小型追踪器设计方案(05-20)
- 基于GPSOne技术的个人定位终端(07-30)
- 2010年中国(成都)电子展胜利闭幕(08-15)
- 基于DSP的车载GPS/DR组合导航系统硬件设计(09-13)
- 基于MiniGUI的GPS导航定位系统设计(02-20)