NMEA 解析程序

经常需求使用 GPS 串口 NMEA 解析的功能,写了一段代码来完成引功能。
分享一下,大家一起学习。

头文件:

 1 #ifndef _GPS_MONITER_HH_
 2 #define _GPS_MONITER_HH_
 3
 4 BOOL InitSerailPort(CString csSerialPort,LPVOID pParent = NULL);
 5 DWORD WINAPI ReadNMEAThread(LPVOID lpParameter);
 6 void SetSystemTimeFormUTC(CString csDate,CString csUTCTime);
 7
 8 void DeinitSerialPort(void);
 9
10 #endif  

源文件:

  1 #include "stdafx.h"
  2 #include "GPSMoniter.h"
  3
  4 #define SATTATOLNUMBER  32
  5
  6 // 用于在 GPS 监控界面显示 NMEA 信息
  7 char gcBuff[4096];
  8
  9 CString gcsTime;
 10 CString gcsDate;
 11 int gdSignalNumber[SATTATOLNUMBER];
 12 CString csLat;
 13 CString csLatdir;
 14 CString csLon;
 15 CString csLondir;
 16 CString csAltitude;
 17 CString csSpeed;
 18 CString csOrientation;
 19 int nNumDisplayed;
 20 int giGSVSatNumber;
 21
 22 HANDLE ghCommHandle;
 23 HANDLE nmeathread_hand;                         // Global handle to the NMEA reading thread
 24
 25 CString gcsGPSState;    //定位: A; 导航: V
 26 CString gcsTimeOp;
 27 CString gcsLatField;
 28 CString gcsLonField;
 29 int giResult;
 30
 31 int giSalNumber;
 32 int giGSVCurrentPackage;
 33
 34 int giHourDiff;
 35
 36 BOOL InitSerailPort(CString csSerialPort,LPVOID pParent)
 37 {
 38     DCB commDCB;
 39     COMMTIMEOUTS timeouts;
 40
 41     ghCommHandle = CreateFile(csSerialPort, GENERIC_READ | GENERIC_WRITE, 0, NULL,
 42         OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, NULL);
 43     if(INVALID_HANDLE_VALUE == ghCommHandle)
 44     {
 45         RETAILMSG(1, (TEXT("Opening GPS %s failed: %d!\r\n"),csSerialPort,(int)GetLastError()));
 46         return FALSE;
 47     }
 48
 49     commDCB.DCBlength = sizeof (DCB);
 50     if(!GetCommState(ghCommHandle,&commDCB))
 51     {
 52         CloseHandle(ghCommHandle);
 53         ghCommHandle = INVALID_HANDLE_VALUE;
 54          RETAILMSG(1,(L"Failed in getting GPS %s DCB settings: %d!\r\n",csSerialPort,(int)GetLastError()));
 55         return FALSE;
 56     }
 57     commDCB.DCBlength = sizeof(DCB);
 58     commDCB.BaudRate = 9600;             // Current baud
 59     commDCB.ByteSize = 8;                 // Number of bits/bytes, 4-8
 60     commDCB.Parity = NOPARITY;            // 0-4=no,odd,even,mark,space
 61     commDCB.StopBits = ONESTOPBIT;        // 0,1,2 = 1, 1.5, 2
 62
 63     // Setting serial port to Centrality speicifcations
 64     if(!SetCommState(ghCommHandle,&commDCB))
 65     {
 66         CloseHandle(ghCommHandle);
 67         ghCommHandle = INVALID_HANDLE_VALUE;
 68         RETAILMSG(1,(L"Error in trying to set GPS %s DCB settings: %d!\r\n",csSerialPort,(int)GetLastError()));
 69         return FALSE;
 70     }
 71
 72     // Get the default timeout settings for port
 73     if(!GetCommTimeouts(ghCommHandle, &timeouts))
 74     {
 75         CloseHandle(ghCommHandle);
 76         ghCommHandle = INVALID_HANDLE_VALUE;
 77         RETAILMSG(1,(L"Failed in getting GPS %s timeout settings: %d!\r\n",csSerialPort,(int)GetLastError()));
 78         return FALSE;
 79     }
 80     // RETAILMSG(1,(L"%s DCB set successfully!\r\n",csSerialPort));
 81
 82     // Change the timeouts structure settings to Centrality settings
 83     timeouts.ReadIntervalTimeout = 500;
 84     timeouts.ReadTotalTimeoutMultiplier = 0;
 85     timeouts.ReadTotalTimeoutConstant = 0;
 86
 87     // Set the time-out parameters for all read and write operations on the port.
 88     if(!SetCommTimeouts(ghCommHandle,&timeouts))
 89     {
 90         CloseHandle(ghCommHandle);
 91         ghCommHandle = INVALID_HANDLE_VALUE;
 92         RETAILMSG(1,(L"Error in trying to set GPS %s timeout settings: %d!\r\n",csSerialPort,(int)GetLastError()));
 93         return FALSE;
 94     }
 95
 96     if(0 != SetCommMask(ghCommHandle,EV_RXCHAR))
 97     {
 98         RETAILMSG(1,(L"==Set %s mask OK!\r\n",csSerialPort));
 99     }
100     else
101     {
102         RETAILMSG(1,(TEXT("==Set %s mask failure:%d!\r\n"),csSerialPort,GetLastError()));
103     }
104
105     nmeathread_hand = CreateThread(NULL,0,ReadNMEAThread,pParent,0,NULL);
106     //nmeathread_hand = CreateThread(NULL, 0, ReadNMEAThread, this, CREATE_SUSPENDED, NULL);
107     if(!nmeathread_hand)
108     {
109         RETAILMSG(1, (L"Could not create NMEA read thread.\r\n"));
110         return FALSE;
111     }
112     else
113     {
114         //SetThreadPriority(nmeathread_hand, THREAD_PRIORITY_BELOW_NORMAL);
115         //ResumeThread(nmeathread_hand);
116     }
117
118     SYSTEMTIME stUTC;
119     SYSTEMTIME stLocal;
120
121     GetLocalTime(&stLocal);
122     GetSystemTime(&stUTC);
123     giHourDiff = stLocal.wHour - stUTC.wHour;
124
125     return TRUE;
126 }
127
128 // nmeathread_hand = CreateThread(NULL, 0, ReadNMEAThread, this, 0, NULL);
129 DWORD WINAPI ReadNMEAThread(LPVOID lpParameter)
130 {
131     //DECLARE_USER_MESSAGE(UWM_NEW_NMEA);
132
133     int start, endline, onestart, oneend, linelen, degdig, iPos;
134     ULONG bytesRead;
135     DWORD EventMask = EV_RXCHAR;
136     CString field;
137     TCHAR *stopstring;
138
139     static int iCount = 0;
140
141     CWnd *mpNmea;
142     mpNmea = (CWnd*)lpParameter;
143
144     // Wait on the event
145     while(WaitCommEvent(ghCommHandle, &EventMask, NULL))
146     {
147         // RETAILMSG(1,(TEXT("---------------------------------------------ReadNMEAThread:%d,Tick: %d\r\n"),iCount++,GetTickCount()));
148         // Clear the buffer before you start reading
149         memset(gcBuff, 0, 4096);
150
151         // Read from serial port (4b)
152         if (ReadFile(ghCommHandle, gcBuff, 4096, &bytesRead, NULL))
153         {
154             if(bytesRead == 0)
155                 continue;
156
157             CString dacstr(gcBuff); /*Leo:从串口读GPS卫星数据*/
158
159             start = 0;
160             endline = 0;
161
162             // Parse/Process the output (4c)
163             while(1)
164             {
165                 int i = 0;
166                 start = dacstr.Find(L"$G", start);
167                 if(start < 0)
168                     break;
169                 endline = dacstr.Find(L"\r\n", start);
170                 if(endline < 0)
171                     break;
172
173                 linelen = endline - start;
174                 //DebugOutput(MSG_DEBUG, "GPSViewer msg: start = %d endline = %d length = %d", start, endline, linelen);
175
176                 // Extract one line
177                 CString oneline;
178
179                 oneline = dacstr.Mid(start, linelen);
180 #if _DEBUG
181                 // RETAILMSG(1,(TEXT("*******************************GPSViewer msg: Oneline = %s\r\n"),oneline));
182 #endif
183
184                 onestart = 0;
185                 oneend = 0;
186                 i = 0;
187                 //////////////////////////////////////////////////////////////////////////
188                 //$GPRMC,075017.31,V,2232.6057,N,11356.3074,E,,,190708,,W,N*15
189                 //$GPRMC,080525.82,A,2232.5196,N,11356.3719,E,,,190708,,W,A*08
190                 if(oneline.Left(6) == L"$GPRMC")
191                 {
192                     while((iPos = oneline.Find(L",")) >= 0)
193                     {
194                         field = oneline.Left(iPos);
195                         i ++;
196                         oneline = oneline.Mid(iPos + 1);
197
198                         if(3 == i)
199                         {
200                             gcsGPSState = field;
201                         }
202                         else if(10 == i)        // <9>当前UTC日期ddmmyy 格式 - 例如: 030222
203                         {
204                             gcsDate = field;
205                         }
206                     }
207                 }
208                 //////////////////////////////////////////////////////////////////////////
209                 //$GPGGA,080514.82,2232.5203,N,11356.3719,E,1,6,1.327,239.386,M,,M,,*4D
210                 else if(oneline.Left(6) == L"$GPGGA")
211                 {
212                     while((iPos = oneline.Find(L",")) >= 0)
213                     {
214                         static int iOrientation = 0;
215
216                         field = oneline.Left(iPos);
217                         i ++;
218                         oneline = oneline.Mid(iPos + 1);
219                         if (i == 2)
220                         {
221                             //////////////////////////////////////////////////////////////////////////
222                             if(iOrientation != giResult)
223                             {
224                                 RETAILMSG(1,(L"[GPS]Status of GPS is changed: %d(Old: %d)\r\n",giResult,iOrientation));
225                                 iOrientation = giResult;
226                             }
227                             //////////////////////////////////////////////////////////////////////////
228                             gcsTimeOp = field;
229                             // 将格式从: --:--:--.-- 修改为: --:--:-- ,即不显示秒后的数据 ---Leo 2009-03-26
230                             CString csTmp = gcsTimeOp.Right(5);
231                             CString csHour = gcsTimeOp.Left(2);
232                             int iHour = _wtoi(csHour);
233
234                             if(iHour + giHourDiff < 24)
235                             {
236                                 csHour.Format(L"%d",iHour + giHourDiff);
237                             }
238                             else
239                             {
240                                 csHour.Format(L"%d",((iHour + giHourDiff) - 24));
241                             }
242                             // gcsTime = csHour + L":" + time.Mid(2,2) + L":" + csTmp.Left(2);
243                             gcsTime = csHour + gcsTimeOp.Mid(2,2) + csTmp.Left(2);
244                         }
245                         else if (i == 3)
246                         {   //Get Latitude from GGA - Value may not be valid.  Check flag to be sure.
247                             gcsLatField = field;
248                             degdig = gcsLatField.GetLength() - 2;
249                             csLat = gcsLatField.Left(2) + CString(" ") + gcsLatField.Right(degdig);
250                         }
251                         else if (i == 4)
252                         {   //Get Latitude Direction (N,S) from GGA - Value may not be valid.  Check flag to be sure.
253                             csLatdir = field;
254                         }
255                         else if (i == 5)
256                         {   //Get Longitude from GGA - Value may not be valid.  Check flag to be sure.
257                             gcsLonField = field;
258                             degdig = gcsLonField.GetLength() - 3;
259                             csLon = gcsLonField.Left(3) + CString(" ") + gcsLonField.Right(degdig);
260                         }
261                         else if (i == 6)
262                         {   //Get Longitude Direction (E,W) from GGA - Value may not be valid.  Check flag to be sure.
263                             csLondir = field;
264                         }
265                         else if (i == 7)    //<6>GPS状态批示0-未定位 1-无差分定位信息 2-带差分定位信息
266                         {   //Get Flag from GGA indicating position fix.  Position output from GGA is valid.
267                             giResult = atoi((const char*)((LPCTSTR)field));
268                             if(0 == giResult)
269                             {
270                                 // RETAILMSG(1,(TEXT("===No orientation\r\n")));
271                             }
272                             else if(1 == giResult)
273                             {
274                                 // RETAILMSG(1,(TEXT("===Orientation with no difference\r\n")));
275                             }
276                             else if(2 == giResult)
277                             {
278                                 // RETAILMSG(1,(TEXT("===Orientation with difference\r\n")));
279                             }
280                         }
281                         else if (i == 10)
282                         {
283                             csAltitude = field;
284                         }
285                     }
286                 }
287                 //$GPGSV,3,3,11,29,21,93,36,30,33,40,36,31,49,324,*46
288                 else if (oneline.Left(6) == L"$GPGSV")
289                 {
290                     while((iPos = oneline.Find(L",")) >= 0)
291                     {
292                         field = oneline.Left(iPos);
293                         i ++;
294                         oneline = oneline.Mid(iPos + 1);
295
296                         if(3 == i)
297                         {
298                             if(_ttoi(field) > 0)
299                             {
300                                 giGSVCurrentPackage = _ttoi(field);
301                                 if (giGSVCurrentPackage == 1) // new GSV sentence
302                                 {
303                                     nNumDisplayed = 0;
304                                     for(int j = 0;j < SATTATOLNUMBER;j++)
305                                     {
306                                         gdSignalNumber[j] = -1;
307                                     }
308                                 }
309                             }
310                         }
311                         else if(4 == i)
312                         {
313                             if(_tcstod(field, &stopstring) > 0)
314                             {
315                                 giGSVSatNumber = (int)_tcstod(field, &stopstring);
316                             }
317                         }
318                         else if(0 == (i - 5) % 4) //卫星的PRV号星号
319                         {
320                             if (_ttoi(field) > 0)
321                             {
322                                 giSalNumber = _ttoi(field);
323                             }
324                         }
325                         else if(3 == (i - 5) % 4) // SNR
326                         {
327                             if (_ttoi(field) > 0)
328                             {
329                                 gdSignalNumber[giSalNumber-1] = _ttoi(field);
330                                 nNumDisplayed++;
331                             }
332                         }
333                     }
334                     if ((iPos = oneline.Find(L"*")) >= 0) // last sat
335                     {
336                         field = oneline.Left(iPos);
337                         i ++;
338                         if(3 == (i - 5) % 4) // SNR
339                         {
340                             if (_ttoi(field) > 0)
341                             {
342                                 gdSignalNumber[giSalNumber-1] = _ttoi(field);
343                                 nNumDisplayed++;
344                             }
345                         }
346                     }
347                 }
348                 //$GPVTG,<1>,T,<2>,M,<3>,N,<4>,K,<5>*hh
349                 // <1> 对地航向(单位:度)
350                 // <2> 磁偏角(单位:度)
351                 // <3> 对地航速(单位:哩/小时)
352                 // <4> 地面速率(0000.0~1851.8公里/小时,前面的0也将被传输)
353                 //如: $GPVTG,359.95,T,,M,15.15,N,28.0,K,A*04
354                 else if(oneline.Left(6) == L"$GPVTG")
355                 {
356                     while((iPos = oneline.Find(L",")) >= 0)
357                     {
358                         field = oneline.Left(iPos);
359                         i ++;
360                         oneline = oneline.Mid(iPos + 1);
361                         if(2 == i)
362                         {
363                             csOrientation = field;
364                         }
365                         else if(8 == i)
366                         {
367                             csSpeed = field;
368                         }
369                     }
370                 }
371                 start = endline + 2;
372             } // end of buffer processing
373         }
374         //Sleep(1000);// end of ReadFile
375     } // end of WaitCommEvent
376     {
377         // RETAILMSG(1,(TEXT("Exit GPS thread:%d"),GetLastError()));
378     }
379
380     return 0;
381 }// end of ReadNMEAThread
382
383
384 //csDate: 01-01-03
385 //csUTCTime: 04:07:44.08
386 void SetSystemTimeFormUTC(CString csDate,CString csUTCTime)
387 {
388     SYSTEMTIME st;
389     int iHour = 0;
390     int iMinute = 0;
391     int iSecond = 0;
392     int iYear = 0;
393     int iMonth = 0;
394     int iDay = 0;
395     CString csSubString;
396     TCHAR *stopstring;
397     // RETAILMSG(1,(TEXT("====Set system time from UTC.Date: %s, Time: %s"),csDate,csUTCTime));
398
399     GetSystemTime(&st);
400
401     csSubString = csDate.Left(2);
402     iDay = (int)_tcstod(csSubString, &stopstring);
403
404     csSubString = csDate.Mid(3,2);
405     iMonth = (int)_tcstod(csSubString, &stopstring);
406
407     csSubString = csDate.Right(2);
408     iYear = 2000 + (int)_tcstod(csSubString, &stopstring);
409
410     st.wYear = iYear;
411     st.wMonth = iMonth;
412     st.wDay = iDay;
413
414     csSubString = csUTCTime.Left(2);
415     iHour = (int)_tcstod(csSubString, &stopstring);
416
417     csSubString = csUTCTime.Mid(3,2);
418     iMinute = (int)_tcstod(csSubString, &stopstring);
419
420     csSubString = csUTCTime.Mid(6,2);
421     iSecond = (int)_tcstod(csSubString, &stopstring);
422
423     st.wHour = iHour;
424     st.wMinute = iMinute;
425     st.wSecond = iSecond;
426
427     SetSystemTime(&st);
428 }
429
430 void DeinitSerialPort(void)
431 {
432     SetCommMask(ghCommHandle,0);
433
434     if(nmeathread_hand)
435     {
436         TerminateThread(nmeathread_hand,1);
437         CloseHandle(nmeathread_hand);
438     }
439     if(INVALID_HANDLE_VALUE != ghCommHandle)
440     {
441         EscapeCommFunction(ghCommHandle,CLRDTR);
442         EscapeCommFunction(ghCommHandle,CLRRTS);
443         //清除驱动程序内部的发送和接收队列
444         PurgeComm(ghCommHandle,PURGE_TXCLEAR|PURGE_RXCLEAR);
445
446         CloseHandle(ghCommHandle);
447         ghCommHandle = INVALID_HANDLE_VALUE;
448     }
449 }  
时间: 2024-10-14 04:57:59

NMEA 解析程序的相关文章

Android解析程序包时出现问题

Android用户下载我们wcc应用时,偶尔会出现“解析程序包出现问题”的的现象,以下是逐步排查的相关经验: 1. 首先确保这个包本身没有问题. 检测方法:其他手机采用同样的下载方式再下载一次. 解决方案: android系统不支持包名包含中文文件名和全角字母符号,如果在应用程序中使用了,请做修改. android系统不支持包名以大写字母开头,如有请改为小写. 2. 再确保下载的包是完整的,下载过程可能出现apk文件损害,导致没有办法解析. 检测方法:比较下载的apk和服务器的apk size是

重写慢日志解析程序,实现打印慢SQL信息及其所属数据库

分组自研的审计平台最近推出慢SQL优化的功能,topN慢SQL可以通过mysqldumpslow拿到,但由于mysqldumpslow输出的信息不包含数据库,这让程序后续的自动优化变得有些棘手.在观察了MySQL慢日志结构后,决定自己写一个python解析程序,返回的结果比mysqldumpslow解析结果上多出数据库名称这一列: Count: 15 Time=0.002961s (0.034505s) Lock=8.8e-05s (0.000767s) Rows=446 (6690), dbm

dnsquery - 使用解析程序查询域名服务器

SYNOPSIS(总览) dnsquery [-n nameserver ] [-t type ] [-c class ] [-r retry ] [-p period ] [-d ] [-s ] [-v ] host DESCRIPTION(描述) dnsquery 程序是一个通过BIND解析程序库调用到域名服务器的通用接口. 该程序支持使用一些查询操作码来查询域名服务器. 该程序意在作为程序如nstest,nsquery和nslookup的替换或补充. 所有参数,除了 host 和 name

请大家帮我找一找bug —— 一个MySQL解析程序(JAVA实现)

周末两天我写了一个MySQLParser.写这个东西的目的是:公司的一个项目中需要对数据打版本号(每个表的每条记录要有一个版本号字段,这个字段需要由框架自动打上去,而不是由程序员来做). 所以,我写的这个程序是有专门的场景的,并非为通用情况而编写(也就是说:有些东西并不影响工具对sql加字段的,我在编写的过程中故意的忽略了.比如:系统中只用到CRUD操作,所以我在写SQL时就没能支持DDL语句). 我已经测试了项目系统中的所有SQL,都是可以处理的,同时我也自己写了一些比较复杂的SQL,也可以正

笔记12:简易的二维码生成解析程序

首先得引用一个文件.直接看代码吧! 1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Drawing; 5 using System.Data; 6 using System.Text; 7 using System.Windows.Forms; 8 using ThoughtWorks.QRCode.Codec; 9 using ThoughtWor

ARP解析程序

//ProtoHead.h 1 #define IP_PROTO 0X0800 2 #define ARP_PROTO 0X0806 3 4 /*以下是以太网协议格式*/ 5 struct ether_header 6 { 7 unsigned char ether_dhost[6]; //目的Mac地址 8 unsigned char ether_shost[6]; //源Mac地址 9 unsigned short ether_type; //协议类型 10 }; 11 12 /*下面是AR

json数据源文件解析

文章: http://blog.csdn.net/lili72 背景: 分布式文件通过rsync同步到生产机. 文件数 1440=24*60  也就是一分钟生成一个文件 文件命名 0000 0001 0002 ... 2358 2359 .由于文件传过来是JSON格式,需要对文件进行解析,导入HDFS中. 过程 1  rsync同步文件到当天的日期目录,每天实时把文件同步到生产机制定目录,每天生成新文件夹,由于是每分钟生成文件,每个文件夹都有1440个文件. 1.1  修改配置文件,增加一个目录

了解URL编码的基本概念,在javascript和java程序中使用内置的API进行编码和解码

1.URL编码的基本概念 URL只能使用US-ASCII 字符集来通过因特网进行发送.由于URL常常会包含 ASCII 集合之外的字符,URL必须转换为有效的 ASCII 格式.URL 编码使用 "%" 其后跟随两位的十六进制数来替换非 ASCII 字符.URL 不能包含空格,URL 编码通常使用 + 来替换空格.所谓URL编码,就是将非US-ASCII字符和US-ASCII中的特殊字符,用相应的字符集编码来表示.比如,汉字"你",如果用UTF-8编码,出现在URL

(九)shell中case语句、程序传参、while

2.2.6.1.case语句(1)shell中的case语句和C语言中的switch case语句作用一样,格式有差异(2)shell中的case语句天生没有break,也不需要break,和C语言中的switch case不同.shell中的case默认就是匹配上哪个执行哪个,不会说执行完了还去执行后面的其他case(就好像shell中的case语言默认都带了break). 2.2.6.2.调用shell程序的传参(1)C语言中可以通过main函数的argc和argv给程序传参(详情参考<4.