您的位置:首页 > 编程语言

GPS数据格式解析源代码举例

2011-09-09 16:56 483 查看
GPS数据格式解析源代码举例

随着内置GPS的手机越来越多,GPS相关的应用也越来越广泛,GPS已经不仅仅只是得到一个经纬度的信息,可以通过GPS开发出更多的应用,比如位置图片,比如好友位置显示,比如跟踪等等,TimeSyncPPC就是可以使用GPS的时钟来进行时间同步的。

所有这些功能都需要知道GPS的数据格式并能够解析出自己需要的数据出来。下面就以TimeSyncPPC中如何得到GPS的日期和时间为例来说明如何解析GPS数据。

TimeSyncPPC是用于Pocket PC上的时间同步工具,因此得到GPS的时间和日期,使用的GPS的指令是$GPRMC,其指令格式如下:

$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>

1) 标准定位时间(UTC time)格式:时时分分秒秒.秒秒秒(hhmmss.sss)。

2) 定位状态,A = 数据可用,V = 数据不可用。

3) 纬度,格式:度度分分.分分分分(ddmm.mmmm)。

4) 纬度区分,北半球(N)或南半球(S)。

5) 经度,格式:度度分分.分分分分。

6) 经度区分,东(E)半球或西(W)半球。

7) 相对位移速度, 0.0 至 1851.8 knots

8) 相对位移方向,000.0 至 359.9度。实际值。

9) 日期,格式:日日月月年年(ddmmyy)。

10) 磁极变量,000.0 至180.0。

11) 度数。

12) Checksum.(检查位)

从数据格式中可以看出,我们需要得到1和9两个字段的数据即可。

当然,使用GPS首先要打开GPS的串口,代码如下:

HANDLE OpenCom(CString strCom, DWORD BaudRate, BYTE ByteSize, BYTE StopBits, BYTE Parity, int FlowControl)

{

HANDLE hCommPort;

CString strTemp;

if((hCommPort = CreateFile(strCom, GENERIC_READ | GENERIC_WRITE, 0,

NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)

{

return NULL;

}

DCB commDCB;

CString strWinText;

GetCommState(hCommPort, &commDCB);

commDCB.BaudRate = BaudRate;

commDCB.ByteSize = ByteSize;

commDCB.StopBits = StopBits;

commDCB.fParity = (NOPARITY == Parity) ? FALSE : TRUE;

commDCB.Parity = Parity;

commDCB.fDsrSensitivity = FALSE;

commDCB.fDtrControl = DTR_CONTROL_ENABLE;

if(FlowControl == 1) // Hardware

{

// Enable RTS/CTS Flow Control

commDCB.fRtsControl = RTS_CONTROL_HANDSHAKE;

commDCB.fOutxCtsFlow = 1;

commDCB.fOutX = 0;

commDCB.fInX = 0;

}

else if(FlowControl == 0) // Software

{

// Enable XON/XOFF Flow Control

commDCB.fRtsControl = RTS_CONTROL_ENABLE;

commDCB.fOutxCtsFlow = 0;

commDCB.fOutX = 1;

commDCB.fInX = 1;

}

else

{

commDCB.fRtsControl = RTS_CONTROL_ENABLE;

commDCB.fOutxCtsFlow = 0;

commDCB.fOutX = 0;

commDCB.fInX = 0;

}

SetCommState(hCommPort, &commDCB);

return hCommPort;

}

串口打开后需要得到一行GPS数据,GPS数据是以结束,代码如下:

// 返回值为-1:超时,其他值为数据长度

int GetGPSLineData(HANDLE hCommPort, char *ReadBuf, int Length)

{

// 读一行GPS数据

DWORD nBytes;

int i = 0;

DWORD TimeOut = 0;

while(i < Length)

{

if(g_isQuit)

return i;

TimeOut ++;

if(TimeOut >= 100)

return -1;

ReadFile(hCommPort, (LPVOID)&ReadBuf[i], 1, &nBytes, NULL);

if(nBytes == 0)

{

Sleep(1);

continue;

}

TimeOut = 0;

if(ReadBuf[i] == 0x0d)

{

ReadBuf[i] = 0;

break;

}

if(ReadBuf[i] == 0x0a)

{

continue;

}

i ++;

}

return i;

}

下面是解析一行GPS数据,将数据结果存储在一个数组中,代码如下:

// 解析一行GPS数据

int AnalyzeGPSData(char *GPSData, int Length, char Command[][100])

{

int i = 0;

int j = 0, k = 0;

while(i < Length)

{

if(GPSData[i] == ',')

{

Command[j][k] = 0;

j ++;

k = 0;

i ++;

continue;

}

Command[j][k] = GPSData[i];

k ++;

i ++;

}

return j;

}

解析之后的GPS数据包含命令和参数,下面就是判断是否是我们需要的命令,如果是得到第一个和第九个参数即可。不过要注意,GPS时间是世界标准时间,因此要转换成本地时间,代码如下:

DWORD WINAPI GetGPSTime(LPVOID lpParameter)

{

char ReadBuf[1000];

DWORD TimeOut = 0;

char Command[40][100];

HANDLE hCommPort = OpenCom(g_strComPort, g_BaudRate);

if(hCommPort == NULL)

{

MessageBox(NULL, _T("Can not open COM port!"), NULL, MB_OK | MB_TOPMOST);

goto GPSExit;

}

while(1)

{

if(g_isQuit)

break;

// 读一行GPS数据

int Length = GetGPSLineData(hCommPort, ReadBuf, 999);

if(Length == -1)

{

TimeOut ++;

if(TimeOut < 100)

continue;

}

if(TimeOut >= 100)

{

MessageBox(NULL, _T("Read GPS data timeout!"), NULL, MB_OK | MB_TOPMOST);

goto GPSExit;

}

TimeOut = 0;

AnalyzeGPSData(ReadBuf, Length, Command);

if(strcmp(Command[0], "$GPRMC") == 0)

{

SYSTEMTIME st, LocalSt;

st.wHour = (Command[1][0] - '0') * 10 + (Command[1][1] - '0');

st.wMinute = (Command[1][2] - '0') * 10 + (Command[1][3] - '0');

st.wSecond = (Command[1][4] - '0') * 10 + (Command[1][5] - '0');

st.wMilliseconds = (Command[1][7] - '0') * 100 + (Command[1][8] - '0') * 10 + (Command[1][9] - '0');

st.wDay = (Command[9][0] - '0') * 10 + (Command[9][1] - '0');

st.wMonth = (Command[9][2] - '0') * 10 + (Command[9][3] - '0');

st.wYear = (Command[9][4] - '0') * 10 + (Command[9][5] - '0') + 2000;

FILETIME FileTime, LocalFileTime;

SystemTimeToFileTime(&st, &FileTime);

FileTimeToLocalFileTime(&FileTime, &LocalFileTime);

FileTimeToSystemTime(&LocalFileTime, &LocalSt);

g_GPSDateCtrl->SetTime(LocalSt);

g_GPSTimeCtrl->SetTime(LocalSt);

if(strcmp(Command[2], "A") == 0)

{

BOOL ret = SetSystemTime(&st);

MessageBox(NULL, _T("SyncTime Success!"), _T(""), MB_OK | MB_TOPMOST);

strGPSButton = _T("Get GPS Time");

g_ThisDlg->SetDlgItemText(IDC_GETGPSTIME, strGPSButton);

g_ThisDlg->GetDlgItem(IDC_SETGPSTIME)->EnableWindow(0);

break;

}

else

{

TimeOut ++;

}

}

}

GPSExit:

if(hCommPort != NULL)

CloseHandle(hCommPort);

g_GetGPSTimeThread = NULL;

strGPSButton = _T("Get GPS Time");

g_ThisDlg->SetDlgItemText(IDC_GETGPSTIME, strGPSButton);

g_ThisDlg->GetDlgItem(IDC_SETGPSTIME)->EnableWindow(0);

return TRUE;

}

如果需要解析其他指令,可以参考函数DWORD WINAPI GetGPSTime(LPVOID lpParameter)的实现方法,其实还是比较简单的。

这些代码已经在TimeSyncPPC中测试过,可以直接使用,开发环境为VS2005,Windows Mobile 6.1 for PPC。如有疑问请在下方留言
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: