java 使用串口获取gps
目前GPS(全球定位系统)定位应用市场日趋成熟,正在进入应用的高速发展时期。看到论坛里不断有人提问关于GPS的问题。现将个人对GPS的了解写出来跟大家一块探讨。
1、 GPS应用简介
近年来GPS系统,已经在大地测绘、海上渔用、车辆定位监控、建筑、农业等各个领域得到广泛应用。从九十年代我国引进GPS定位技术开始,经过十多年的市场培育,GPS定位应用进入了发展的最好时机,未来十年基于GPS的应用将会改变我们的生活和工作方式。
目前市场上的大部分GPS接受模块都是通过RS232串口与MCU进行数据传输的。这些数据包括经度、纬度、海拔高度、时间、卫星使用情况等基本信息。开发人员再依据这些基本数据,进行数据处理来完成整套的定位系统软件。
2、 数据格式
在进行数据接受编程之前,先介绍一下该模块的数据格式。它支持NMEA-0183输出格式。信息如下:
GGA位置测定系统定位资料(Global Positioning System Fix Data)
GSV 导航卫星资料(GNSS Satellites in View)
RMC导航卫星特定精简资料(Recommended Minimum Specific GNSS Data)
VTG 方向及速度等相关资料(Course Over Ground and Ground Speed)
由于文章篇幅问题,笔者在这里只以接收GGA数据为例,格式如下:
$GPGGA,hhmmss,dddmm.mmmm,a,dddmm.mmmm,a,x,xx,x.x,x.x,M,,M,x.x,xxxx*CS
例:$GPGGA,033744,2446.5241,N,12100.1536,E,1,10,0.8,133.4,M,,,,*1F
说明见表:
区域
名称
例
单位
说明
1
信息ID
$GPGGA
GGA协议开始
2
UTC时间
033744
hhmmss
3
纬度
2446.5241
dddmm.mmmm
4
南/北半球指示
N
N=north;S=south
5
经度
12100.1536
dddmm.mmmm
6
东/西半球指示
E
E=east;W=west
7
定位指示
1
0 =未定位
1=定位SPS模式
2=定位DGPS, SPS模式
8
应位卫星数
10
00-12
9
HDOP
0.8
米
10
海拔高度
133.4
米
11
海拔高度单位
M
米
12
WGS84水准面划分
13
WGS-84水准面划分单位
14
累计GPS数据微分
15
参考工作站ID
16
校验位
*1F
上面例子中,我们可读出位置信息:北纬24度46.5241分,西经121度00.1536分
格林威治时间:3点37分44秒
3 部分程序代码(c++)
//初始化串口
//入口:strComm(串口名)
//返回:TRUE(成功);FALSE(失败)
BOOLCGPSDlg::InitComm(CString strComm)
{
inti;
DCB dcb;
COMMTIMEOUTS TimeOuts;
for(i=0; i<3; i++)//串口最多初始化3次
{
m_hComm = CreateFile(strComm, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if(m_hComm != INVALID_HANDLE_VALUE)
break;
}
if(i == 3)//串口初始化失败
{
AfxMessageBox('串口初始化失败...');
returnFALSE;
}
SetupComm(m_hComm, MAXLENGTH, MAXLENGTH);//设置发送接收缓冲区大小
TimeOuts.ReadIntervalTimeout = 0;//设定5个超时参数
TimeOuts.ReadTotalTimeoutMultiplier = 0;
TimeOuts.ReadTotalTimeoutConstant = 500;
TimeOuts.WriteTotalTimeoutMultiplier = 0;
TimeOuts.WriteTotalTimeoutConstant = 500;
SetCommTimeouts(m_hComm, &TimeOuts);//设置超时参数
GetCommState(m_hComm, &dcb);//获得通信状态
dcb.fAbortOnError = FALSE;//有错误不停止
dcb.BaudRate = CBR_4800;//波特率4800
dcb.ByteSize = 8;//8位
dcb.Parity = NOPARITY;//奇校验
dcb.StopBits = ONESTOPBIT;//1位停止位
SetCommState(m_hComm, &dcb);//设置通信状态
PurgeComm(m_hComm, PURGE_TXCLEAR|PURGE_RXCLEAR);//清空发送和接收缓冲区
returnTRUE;
}
//获得GPS参数
//注意:从GPS接收到的字符串已经在m_strRecv中,由于是定时接收,所以在这个字符串的头和尾都可能存在
// 不完整的NMEA输出字符串,在处理时要特别注意
//返回:TRUE(格式正确);FALSE(格式错误)
BOOLCGPSDlg::GetGPSParam()
{
inti,j;
CString str,strNEMA;
//先判断是否接收到数据
if(m_strRecv.IsEmpty())
returnFALSE;
//若字符串不是以'$'开头的,必须删掉这部分不完整的
if(m_strRecv[0] !='$')
{
i = m_strRecv.Find('/n', 0);
if(i == -1)
returnFALSE;//尾部未接收完整,必须等接收完后才能删除
m_strRecv.Delete(0, i+1);//尾部已接收完整(尾部为/r/n结束),删除不完整的部分
}
//截取完整的NMEA-0183输出语句(m_strRecv中可能有多条语句,每条间以/r/n分隔)
for(;;)
{
i = m_strRecv.Find('/n', 0);
if(i == -1)
break;//所有的完整输出语句都已经处理完毕,退出循环
//截取完整的NMEA-0183输出语句
strNEMA = m_strRecv.Left(i+1);
m_strRecv.Delete(0, i+1);
//下面对各种输出语句进行分别处理
if(strNEMA.Find('$GPRMC',0) == 0)
{
//该输出语句中的各项以','分隔
for(i=j=0; strNEMA[i]!='/r'; i++)//j为逗号的计数器
{
if(strNEMA[i] ==',')
{
j++;
str ='';
for(i++; strNEMA[i]!=','&&strNEMA[i]!='/r'; i++)
str += strNEMA[i];//str为某项的值
i--;
//对各项数据分别处理
switch(j)
{
case1://时间(UTC)
m_strTime = str.Left(6);
m_strTime.Insert(2,':');
m_strTime.Insert(5,':');
break;
case2://状态(A-数据有效;V-数据无效,还未定位)
if(str =='A')
m_strStatus ='有效数据';
elseif(str =='V')
m_strStatus ='正在定位...';
else
m_strStatus ='非法数据格式';
break;
case3://纬度(ddmm.mmmm)
str.Insert(2,'度');
str +='分';
m_strLatitude = str;
break;
case4://纬度指示(N-北纬;S-南纬)
if(str =='N')
m_strLatitude.Insert(0,'北纬');
else
m_strLatitude.Insert(0,'南纬');
break;
case5://经度(dddmm.mmmm)
str.Insert(3,'度');
str +='分';
m_strLongitude = str;
break;
case6://经度指示(E-东经;W-西经)
if(str =='E')
m_strLongitude.Insert(0,'东经');
else
m_strLongitude.Insert(0,'西经');
break;
case7://速度(单位:节)
m_strSpeed = str;
break;
case8://航向(单位:度)
m_strCourse = str;
break;
case9://日期(UTC)
m_strDate ='';
m_strDate +='20';
m_strDate += str[4];
m_strDate += str[5];
m_strDate +='-';
m_strDate += str[2];
m_strDate += str[3];
m_strDate +='-';
m_strDate += str[0];
m_strDate += str[1];
break;
default:
break;
}
}
}
}
elseif(strNEMA.Find('$GPGGA',0) == 0)
{
}
elseif(strNEMA.Find('$GPGSA',0) == 0)
{
}
elseif(strNEMA.Find('$GPGSV',0) == 0)
{
}
elseif(strNEMA.Find('$GPGLL',0) == 0)
{
}
elseif(strNEMA.Find('$GPVTG',0) == 0)
{
}
else
returnFALSE;//格式错误
}
returnTRUE;
}