一、须知
1.手持机(PDA)必须有GPS模块,才能通过代码使用串口通信获取GPS相关信息
2.要清楚自己手持机(PDA)固定的GPS通信串口号,如我们公司的手持机获取GPS信息的串口为COM4
3.测试手持机(PDA)是否获取到GPS相关信息,要到室外才能测试出来。
二、制作步骤
(1)新建好win ce项目
(2)封装类
1.CLR_GPS类
1 class CLR_GPS 2 { 3 4 public float latitude = 0; //纬度 5 6 public float longitude = 0; //经度 7 8 public float speed = 0; 9 10 public float status = 0; 11 12 public float direction = 0; 13 14 public float geoideAltitude = 0; 15 16 private System.IO.Ports.SerialPort serialPort; 17 18 CLR_Regex gpsRegex=new CLR_Regex(); 19 20 private bool isOpen = false; 21 22 23 #region 24 private delegate void myTestEventHandler(); 25 public delegate void LocationEventHandler(string Latitude, string Longitude,string status,bool isNorth,bool isEast,string time); 26 public delegate void serialEventHandler(string data); 27 public delegate void TimeEventHandler(string time); 28 public delegate void DateEventHandler(string date); 29 public delegate void satelliteEventHandlde(string n); 30 public delegate void altitudeEventHandler(string altitude); 31 public delegate void satelliteNumberEventHandler(string num); 32 33 34 private string serialData = string.Empty; 35 36 /// <summary> 37 /// refresh serial data 更新串口数据 38 /// </summary> 39 public event serialEventHandler serialportData; 40 41 /// <summary> 42 /// Refresh Location 更新经纬度 43 /// </summary> 44 public event LocationEventHandler refreshLocation; 45 46 47 /// <summary> 48 /// Refresh Time 更新时间 49 /// </summary> 50 public event TimeEventHandler refreshTime; 51 52 53 /// <summary> 54 /// Refresh Date 更新日期 55 /// </summary> 56 public event DateEventHandler refreshDate; 57 58 59 /// <summary> 60 /// Satellite Total 可视卫星数量 61 /// </summary> 62 public event satelliteNumberEventHandler refreshAllNumber; 63 64 /// <summary> 65 /// Refresh effective satellite 更新卫星数量 66 /// </summary> 67 public event satelliteEventHandlde refreshSatellite; 68 69 70 /// <summary> 71 /// Refresh Altitude 更新海拔 72 /// </summary> 73 public event altitudeEventHandler refreshAltitude; 74 75 76 77 #endregion 78 79 80 81 public CLR_GPS() 82 { 83 serialPort = new System.IO.Ports.SerialPort("COM4", 115200); //此处可根据实际情况设置串口 84 serialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(serialPort_DataReceived); 85 86 } 87 88 public CLR_GPS(string portName) 89 { 90 serialPort = new System.IO.Ports.SerialPort(portName, 115200); //此处可根据实际情况设置串口 91 serialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(serialPort_DataReceived); 92 93 } 94 95 96 /// <summary> 97 /// stop Receive data 停止接收数据 98 /// </summary> 99 public void stopReceive() 100 { 101 isOpen = false; 102 Thread.Sleep(300); 103 } 104 105 /// <summary> 106 /// start Receiving 开始接收数据 107 /// </summary> 108 public bool startReceive() 109 { 110 try 111 { 112 isOpen = true; 113 if (!serialPort.IsOpen) 114 { 115 serialPort.Open(); 116 } 117 return true; 118 } 119 catch (System.Exception) 120 { 121 isOpen = false; 122 return false; 123 } 124 125 } 126 127 128 /// <summary> 129 /// initialization 初始化 130 /// </summary> 131 /// <returns></returns> 132 public bool InitModule() 133 { 134 return true; //此处可根据实际情况进行GPS模块的上电 135 136 } 137 138 139 140 public void FreeModule() 141 { 142 try 143 { 144 145 isOpen = false; 146 147 148 if (serialPort.IsOpen) 149 { 150 serialPort.Close(); 151 } 152 153 } 154 catch (Exception) 155 { 156 157 } 158 //此处可根据实际情况进行GPS模块的下电 159 160 } 161 162 void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) 163 { 164 try 165 { 166 serialData = serialData + serialPort.ReadExisting(); 167 if (serialData.Length > 300) 168 { 169 serialData = serialData.Substring(serialData.LastIndexOf('$')); 170 } 171 172 if (isOpen) 173 { 174 if (serialportData != null) 175 { 176 serialportData(serialData); 177 } 178 AnalysisGPSData(serialData); 179 180 } 181 } 182 catch { } 183 184 } 185 186 187 188 189 private void AnalysisGPGGA(string scr) 190 { 191 string altitude = string.Empty; 192 string[] fields = scr.Split(','); 193 194 195 if (fields.Length>10) 196 { 197 string num = fields[7].Trim(); 198 if (num.Length > 0 && gpsRegex.isNumber(num)) 199 { 200 //satelliteNumber = Convert.ToInt32(fields[7].Trim()); 201 if (refreshSatellite != null) 202 { 203 //Effective Satellite 更新使用卫星数量 204 refreshSatellite(num); 205 } 206 } 207 208 if (fields[9].Trim().Length > 0) 209 { 210 //refresh Altitude 更新海拔 211 if (refreshAltitude != null) 212 { 213 refreshAltitude(fields[9].Trim()); 214 } 215 } 216 } 217 218 219 } 220 221 222 private bool AnalysisGPRMC(string scr) 223 { 224 int latiDegree = 400, longiDegree = 400; 225 float latiMinute = 400, longiMinute = 400, speedTemp = 0, directionTemp = direction; 226 string statusTemp = string.Empty; 227 float latitudeTemp = 400, longitudeTemp = 400; 228 bool paramChanged = false; 229 230 bool isNortHemisphere = true; 231 bool isEastHemisphere=true; 232 string time = string.Empty; 233 234 string[] fields = scr.Split(','); 235 236 if (fields.GetLength(0) < 12) 237 return false; 238 // 状态 239 240 string[] utc = fields[1].Trim().Split('.'); 241 242 243 if (utc[0].Trim().Length == 6) 244 { 245 time = utc[0].Trim(); 246 if (refreshTime!=null) 247 { 248 refreshTime(time); 249 } 250 } 251 252 if (fields[2]=="A") 253 { 254 // //= Convert.ToChar(fields[2]); 255 //char d = Convert.ToChar(fields[2]); 256 statusTemp = fields[2]; 257 } 258 // Lati 259 if (fields[3].Length > 5) 260 { 261 if (System.Text.RegularExpressions.Regex.Match(fields[3], @"^[0-9]+[.]?([\d]+)?").Value == fields[3]) 262 { 263 latiDegree = Convert.ToInt32(fields[3].Substring(0, 2), 10); 264 latiMinute = Convert.ToSingle(fields[3].Substring(2, fields[3].Length - 2)); 265 paramChanged = true; 266 } 267 } 268 // NSHemisphere NSHemisphere 南北半球 269 if (fields[4].Length == 1) 270 { 271 //'s' 'S' 272 if (string.Equals(fields[4], "S", StringComparison.CurrentCultureIgnoreCase)) 273 { 274 isNortHemisphere = false; //南半球 275 latitudeTemp = -latitudeTemp; 276 } 277 } 278 // long 279 if (fields[5].Length > 5) 280 { 281 if (System.Text.RegularExpressions.Regex.Match(fields[5], @"^[0-9]+[.]?([\d]+)?").Value == fields[5]) 282 { 283 longiDegree = Convert.ToInt32(fields[5].Substring(0, 3), 10); 284 longiMinute = Convert.ToSingle(fields[5].Substring(3, fields[5].Length - 3)); 285 paramChanged = true; 286 } 287 } 288 // EWHemisphere 东经 西经 289 if (fields[6].Length == 1) 290 { 291 //'w' 'W' 292 if (string.Equals(fields[6], "W", StringComparison.CurrentCultureIgnoreCase)) 293 { 294 isEastHemisphere=false; //西半球 295 longitudeTemp = -longitudeTemp; 296 } 297 } 298 // speed 速率 299 if (fields[7].Length > 2) 300 { 301 if (System.Text.RegularExpressions.Regex.Match(fields[7], @"^[0-9]+[.]?([\d]+)?").Value == fields[7]) 302 { 303 speedTemp = (float)(Convert.ToSingle(fields[7]) * 1.852); 304 paramChanged = true; 305 } 306 } 307 // direction 地面航向 正北为零度 308 if (fields[8].Length > 2) 309 { 310 if (System.Text.RegularExpressions.Regex.Match(fields[8], @"^[0-9]+[.]?([\d]+)?").Value == fields[8]) 311 { 312 directionTemp = Convert.ToSingle(fields[8]); 313 paramChanged = true; 314 } 315 } 316 317 if (fields[9].Trim().Length==6) 318 { 319 if (refreshDate!=null) 320 { 321 refreshDate(trandforDate(fields[9].Trim())); 322 } 323 } 324 if ((latiDegree != 400) && (latiMinute != (float)400.0)) 325 { 326 latitudeTemp = (float)(latiDegree + latiMinute / 60.0); 327 } 328 if ((longiDegree != 400) && (longiMinute != (float)400.0)) 329 { 330 longitudeTemp = (float)(longiDegree + longiMinute / 60.0); 331 } 332 if (paramChanged) 333 { 334 if (refreshLocation != null) 335 { 336 refreshLocation(fields[4]+":"+latitudeTemp.ToString(), fields[6]+":"+longitudeTemp.ToString(), statusTemp,isNortHemisphere,isEastHemisphere, time); 337 } 338 return true; 339 } 340 else 341 return false; 342 } 343 344 345 /// <summary> 346 /// data for date 将GPS数据转换成日期 347 /// </summary> 348 /// <param name="date"></param> 349 /// <returns></returns> 350 string trandforDate(string date) 351 { 352 return "20"+date.Substring(4, 2) + "-" + date.Substring(2, 2) + "-" + date.Substring(0, 2); 353 } 354 355 356 357 358 void AnalysisGPGSV(string scr) 359 { 360 string[] fields = scr.Split(','); 361 362 if (fields.Length>4) 363 { 364 string AllNum = fields[3].Trim(); 365 366 if (AllNum.Length > 0 && gpsRegex.isNumber(AllNum) && refreshAllNumber != null) 367 { 368 //Satellite Total 369 refreshAllNumber(fields[3]); 370 } 371 } 372 373 // 状态 374 } 375 376 377 private void AnalysisGPSData(string sGpsData) 378 { 379 string[] gpsDataSplit = sGpsData.Trim().Split('$'); 380 381 382 foreach (string gps in gpsDataSplit) 383 { 384 if (gps.StartsWith("GPRMC")) 385 { 386 AnalysisGPRMC(gps); 387 } 388 else if (gps.StartsWith("GPVTG")) 389 { 390 AnalysisGPVTG(gps); 391 } 392 else if (gps.StartsWith("GPGGA")) 393 { 394 AnalysisGPGGA(gps); 395 } 396 else if (gps.StartsWith("GPGSV")) 397 { 398 AnalysisGPGSV(gps); 399 } 400 else if (gps.StartsWith("GPGLL")) 401 { 402 403 } 404 } 405 return; 406 } 407 408 409 public void AnalysisGPVTG(string sGpsData) 410 { 411 412 } 413 414 }
2.CLR_Regex类
class CLR_Regex { //public bool includeXing(string msg) //{ // if (Regex.Match(msg, @"^[0-9]+[*]?([\d]+)?").Value == msg) // { // return true; // } // else // return false; //} /// <summary> /// is number ? 是否全是数字 /// </summary> /// <param name="msg"></param> /// <returns></returns> public bool isNumber(string msg) { if (Regex.Match(msg, "^[0-9]*$").Value == msg) { return true; } else return false; } /// <summary> /// is real 是否为实数 /// </summary> /// <param name="msg"></param> /// <returns></returns> public bool isRealData(string msg) { if (msg.StartsWith("-")) { msg = msg.Substring(1); } if (Regex.Match(msg, "^[0-9]+(.[0-9]+)$").Value == msg) { return true; } else return false; } }
3.GPS类
class GPS { public string PortNum; public int BaudRate; public byte ByteSize; public byte Parity; // 0-4=no,odd,even,mark,space public byte StopBits; // 0,1,2 = 1, 1.5, 2 public int ReadTimeout; //comm port win32 file handle private int hComm = -1; public bool Opened = false; //win32 api constants private const uint GENERIC_READ = 0x80000000; private const uint GENERIC_WRITE = 0x40000000; private const int OPEN_EXISTING = 3; private const int INVALID_HANDLE_VALUE = -1; [StructLayout(LayoutKind.Sequential)] public struct DCB { //taken from c struct in platform sdk public int DCBlength; // sizeof(DCB) public int BaudRate; // 指定当前波特率 current baud rate // these are the c struct bit fields, bit twiddle flag to set public int fBinary; // 指定是否允许二进制模式,在windows95中必须主TRUE binary mode, no EOF check public int fParity; // 指定是否允许奇偶校验 enable parity checking public int fOutxCtsFlow; // 指定CTS是否用于检测发送控制,当为TRUE是CTS为OFF,发送将被挂起。 CTS output flow control public int fOutxDsrFlow; // 指定CTS是否用于检测发送控制 DSR output flow control public int fDtrControl; // DTR_CONTROL_DISABLE值将DTR置为OFF, DTR_CONTROL_ENABLE值将DTR置为ON, DTR_CONTROL_HANDSHAKE允许DTR"握手" DTR flow control type public int fDsrSensitivity; // 当该值为TRUE时DSR为OFF时接收的字节被忽略 DSR sensitivity public int fTXContinueOnXoff; // 指定当接收缓冲区已满,并且驱动程序已经发送出XoffChar字符时发送是否停止。TRUE时,在接收缓冲区接收到缓冲区已满的字节XoffLim且驱动程序已经发送出XoffChar字符中止接收字节之后,发送继续进行。FALSE时,在接收缓冲区接收到代表缓冲区已空的字节XonChar且驱动程序已经发送出恢复发送的XonChar之后,发送继续进行。XOFF continues Tx public int fOutX; // TRUE时,接收到XoffChar之后便停止发送接收到XonChar之后将重新开始 XON/XOFF out flow control public int fInX; // TRUE时,接收缓冲区接收到代表缓冲区满的XoffLim之后,XoffChar发送出去接收缓冲区接收到代表缓冲区空的XonLim之后,XonChar发送出去 XON/XOFF in flow control public int fErrorChar; // 该值为TRUE且fParity为TRUE时,用ErrorChar 成员指定的字符代替奇偶校验错误的接收字符 enable error replacement public int fNull; // eTRUE时,接收时去掉空(0值)字节 enable null stripping public int fRtsControl; // RTS flow control /*RTS_CONTROL_DISABLE时,RTS置为OFF RTS_CONTROL_ENABLE时, RTS置为ON RTS_CONTROL_HANDSHAKE时, 当接收缓冲区小于半满时RTS为ON 当接收缓冲区超过四分之三满时RTS为OFF RTS_CONTROL_TOGGLE时, 当接收缓冲区仍有剩余字节时RTS为ON ,否则缺省为OFF*/ public int fAbortOnError; // TRUE时,有错误发生时中止读和写操作 abort on error public int fDummy2; // 未使用 reserved public uint flags; public ushort wReserved; // 未使用,必须为0 not currently used public ushort XonLim; // 指定在XON字符发送这前接收缓冲区中可允许的最小字节数 transmit XON threshold public ushort XoffLim; // 指定在XOFF字符发送这前接收缓冲区中可允许的最小字节数 transmit XOFF threshold public byte ByteSize; // 指定端口当前使用的数据位 number of bits/byte, 4-8 public byte Parity; // 指定端口当前使用的奇偶校验方法,可能为:EVENPARITY,MARKPARITY,NOPARITY,ODDPARITY 0-4=no,odd,even,mark,space public byte StopBits; // 指定端口当前使用的停止位数,可能为:ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS 0,1,2 = 1, 1.5, 2 public char XonChar; // 指定用于发送和接收字符XON的值 Tx and Rx XON character public char XoffChar; // 指定用于发送和接收字符XOFF值 Tx and Rx XOFF character public char ErrorChar; // 本字符用来代替接收到的奇偶校验发生错误时的值 error replacement character public char EofChar; // 当没有使用二进制模式时,本字符可用来指示数据的结束 end of input character public char EvtChar; // 当接收到此字符时,会产生一个事件 received event character public ushort wReserved1; // 未使用 reserved; do not use } [StructLayout(LayoutKind.Sequential)] private struct COMMTIMEOUTS { public int ReadIntervalTimeout; public int ReadTotalTimeoutMultiplier; public int ReadTotalTimeoutConstant; public int WriteTotalTimeoutMultiplier; public int WriteTotalTimeoutConstant; } [StructLayout(LayoutKind.Sequential)] private struct OVERLAPPED { public int Internal; public int InternalHigh; public int Offset; public int OffsetHigh; public int hEvent; } [DllImport("coredll.dll")] private static extern int CreateFile( string lpFileName, // 要打开的串口名称 uint dwDesiredAccess, // 指定串口的访问方式,一般设置为可读可写方式 int dwShareMode, // 指定串口的共享模式,串口不能共享,所以设置为0 int lpSecurityAttributes, // 设置串口的安全属性,WIN9X下不支持,应设为NULL int dwCreationDisposition, // 对于串口通信,创建方式只能为OPEN_EXISTING int dwFlagsAndAttributes, // 指定串口属性与标志,设置为FILE_FLAG_OVERLAPPED(重叠I/O操作),指定串口以异步方式通信 int hTemplateFile // 对于串口通信必须设置为NULL ); [DllImport("coredll.dll")] private static extern bool GetCommState( int hFile, //通信设备句柄 ref DCB lpDCB // 设备控制块DCB ); [DllImport("coredll.dll")] private static extern bool BuildCommDCB( string lpDef, // 设备控制字符串 ref DCB lpDCB // 设备控制块 ); [DllImport("coredll.dll")] private static extern bool SetCommState( int hFile, // 通信设备句柄 ref DCB lpDCB // 设备控制块 ); [DllImport("coredll.dll")] private static extern bool GetCommTimeouts( int hFile, // 通信设备句柄 handle to comm device ref COMMTIMEOUTS lpCommTimeouts // 超时时间 time-out values ); [DllImport("coredll.dll")] private static extern bool SetCommTimeouts( int hFile, // 通信设备句柄 handle to comm device ref COMMTIMEOUTS lpCommTimeouts // 超时时间 time-out values ); [DllImport("coredll.dll")] private static extern bool ReadFile( int hFile, // 通信设备句柄 handle to file byte[] lpBuffer, // 数据缓冲区 data buffer int nNumberOfBytesToRead, // 多少字节等待读取 number of bytes to read ref int lpNumberOfBytesRead, // 读取多少字节 number of bytes read ref OVERLAPPED lpOverlapped // 溢出缓冲区 overlapped buffer ); [DllImport("coredll.dll")] private static extern bool WriteFile( int hFile, // 通信设备句柄 handle to file byte[] lpBuffer, // 数据缓冲区 data buffer int nNumberOfBytesToWrite, // 多少字节等待写入 number of bytes to write ref int lpNumberOfBytesWritten, // 已经写入多少字节 number of bytes written ref OVERLAPPED lpOverlapped // 溢出缓冲区 overlapped buffer ); [DllImport("coredll.dll")] private static extern bool CloseHandle( int hObject // handle to object ); [DllImport("coredll.dll")] private static extern uint GetLastError(); public void Open() { DCB dcbCommPort = new DCB(); COMMTIMEOUTS ctoCommPort = new COMMTIMEOUTS(); // 打开串口 OPEN THE COMM PORT. hComm = CreateFile(PortNum, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); // 如果串口没有打开,就打开 IF THE PORT CANNOT BE OPENED, BAIL OUT. if (hComm == INVALID_HANDLE_VALUE) { throw (new ApplicationException("非法操作,不能打开串口!")); } // 设置通信超时时间 SET THE COMM TIMEOUTS. GetCommTimeouts(hComm, ref ctoCommPort); ctoCommPort.ReadTotalTimeoutConstant = ReadTimeout; ctoCommPort.ReadTotalTimeoutMultiplier = 0; ctoCommPort.WriteTotalTimeoutMultiplier = 0; ctoCommPort.WriteTotalTimeoutConstant = 0; SetCommTimeouts(hComm, ref ctoCommPort); // 设置串口 SET BAUD RATE, PARITY, WORD SIZE, AND STOP BITS. GetCommState(hComm, ref dcbCommPort); dcbCommPort.BaudRate = BaudRate; dcbCommPort.flags = 0; //dcb.fBinary=1; dcbCommPort.flags |= 1; if (Parity > 0) { //dcb.fParity=1 dcbCommPort.flags |= 2; } dcbCommPort.Parity = Parity; dcbCommPort.ByteSize = ByteSize; dcbCommPort.StopBits = StopBits; if (!SetCommState(hComm, ref dcbCommPort)) { //uint ErrorNum=GetLastError(); throw (new ApplicationException("非法操作,不能打开串口!")); } //unremark to see if setting took correctly //DCB dcbCommPort2 = new DCB(); //GetCommState(hComm, ref dcbCommPort2); Opened = true; } public void Close() { if (hComm != INVALID_HANDLE_VALUE) { CloseHandle(hComm); } } public byte[] Read(int NumBytes) { byte[] BufBytes; byte[] OutBytes; BufBytes = new byte[NumBytes]; if (hComm != INVALID_HANDLE_VALUE) { OVERLAPPED ovlCommPort = new OVERLAPPED(); int BytesRead = 0; ReadFile(hComm, BufBytes, NumBytes, ref BytesRead, ref ovlCommPort); try { OutBytes = new byte[BytesRead]; Array.Copy(BufBytes, 0, OutBytes, 0, BytesRead); } catch { return BufBytes; } } else { throw (new ApplicationException("串口未打开!")); } return OutBytes; // return BufBytes; } public void Write(byte[] WriteBytes) { if (hComm != INVALID_HANDLE_VALUE) { OVERLAPPED ovlCommPort = new OVERLAPPED(); int BytesWritten = 0; WriteFile(hComm, WriteBytes, WriteBytes.Length, ref BytesWritten, ref ovlCommPort); } else { throw (new ApplicationException("串口未打开!")); } } public string GetGPS(string strGPS, string strFind) { ///从GPS中读取的数据中,找出想要的数据 ///GPSstring原始字符串, ///strFind要查找的内容,X:经度,Y:纬度,T:时间,V:速度,是数字从1开始,即以“,”分隔的位置 ///返回查找到指定位置的字符串 string handerStr = "$GPRMC";//GPS串头 int findHander = strGPS.IndexOf(handerStr);//看是否含有GPS串头 if (findHander < 0) { return "-1"; } else { strGPS = strGPS.Substring(findHander, strGPS.Length - findHander); string[] ArryTmp = strGPS.Split(",".ToCharArray()); try { if (ArryTmp[2] == "V") { return "V";//没有信号 } else { switch (strFind) { case "X": return DM2DD(ArryTmp[5]); case "Y": return DM2DD(ArryTmp[3]); case "T": return T2Time(ArryTmp[9], ArryTmp[1]); case "V": return Convert.ToString(Convert.ToDouble(ArryTmp[7]) * 1.852); default: return "V"; } } } catch { return "V"; } } } public string T2Time(string strDate, string strTime) { string dT = "20" + strDate.Substring(4, 2) + "-" + strDate.Substring(2, 2) + "-" + strDate.Substring(0, 2); string TT = Convert.ToString(Convert.ToInt32(strTime.Substring(0, 2))) + ":" + strTime.Substring(2, 2) + ":" + strTime.Substring(4, 2); DateTime T = Convert.ToDateTime(dT + " " + TT); T = T.AddHours(8); return T.ToString(); } public string DM2DD(string DegreeMinutes) { //转换NMEA协议的“度分”格式为十进制“度度”格式 string sDegree; string sMinute; string sReturn = ""; if (DegreeMinutes.IndexOf(".") == 4) { //DegreeMinutes = Replace(DegreeMinutes, ".", "") //DM2DD = CDbl(Left(DegreeMinutes, 2)) + CDbl(Left(CStr(CDbl(Right(DegreeMinutes, Len(DegreeMinutes) - 2)) / 60), 8)) / 10000 DegreeMinutes = DegreeMinutes.Replace(".", ""); double sDegree1 = Convert.ToDouble(DegreeMinutes.Substring(0, 2)); double sDegree2 = Convert.ToDouble(DegreeMinutes.Substring(2, DegreeMinutes.Length - 2)); string sTmp = Convert.ToString(sDegree2 / 60); sDegree2 = Convert.ToDouble(sTmp.Substring(0, sTmp.Length)); sDegree2 = sDegree2 / 10000; sDegree = Convert.ToString(sDegree1 + sDegree2); if (sDegree.Length > 11) sDegree = sDegree.Substring(0, 11); sReturn = sDegree; } else if (DegreeMinutes.IndexOf(".") == 5) { //DegreeMinutes = Replace(DegreeMinutes, ".", "") //DM2DD = CDbl(Left(DegreeMinutes, 2)) + CDbl(Left(CStr(CDbl(Right(DegreeMinutes, Len(DegreeMinutes) - 2)) / 60), 8)) / 10000 DegreeMinutes = DegreeMinutes.Replace(".", ""); double sMinute1 = Convert.ToDouble(DegreeMinutes.Substring(0, 3)); double sMinute2 = Convert.ToDouble(DegreeMinutes.Substring(3, DegreeMinutes.Length - 2)); string sTmp = Convert.ToString(sMinute2 / 60); sMinute2 = Convert.ToDouble(sTmp.Substring(0, sTmp.Length)); sMinute2 = sMinute2 / 10000; sMinute = Convert.ToString(sMinute1 + sMinute2); if (sMinute.Length > 10) sMinute = sMinute.Substring(0, 10); sReturn = sMinute; } return sReturn; } public bool ScanPort() { try { if (Opened) { Close(); Open(); } else { Open();//打开串口 } byte[] bytRead = Read(512); Close(); if (Encoding.ASCII.GetString(bytRead, 0, bytRead.Length).IndexOf("$GP") >= 0) return true; else return false; } catch { return false; } } } class HexCon { // 把十六进制字符串转换成字节型和把字节型转换成十六进制字符串 converter hex string to byte and byte to hex string public static string ByteToString(byte[] InBytes) { string StringOut = ""; foreach (byte InByte in InBytes) { StringOut = StringOut + String.Format("{0:X2} ", InByte); } return StringOut; } public static byte[] StringToByte(string InString) { string[] ByteStrings; ByteStrings = InString.Split(" ".ToCharArray()); byte[] ByteOut; ByteOut = new byte[ByteStrings.Length - 1]; for (int i = 0; i == ByteStrings.Length - 1; i++) { ByteOut[i] = Convert.ToByte(("0x" + ByteStrings[i])); } return ByteOut; } }
(3)界面设计
(4)获取GPS相关信息
public partial class TestGps : Form { #region private delegate void mySerial(); private delegate void myTestEventHandler(); //private event myTestEventHandler myTest(); private string gprsData = string.Empty; private bool isClosed = false; public delegate void LocationShow(string Latitude, string Longitude, string status, bool isNorth, bool isEast, string time); public delegate void portDataShow(string data); double beginTime = 0; double endTime = 0; CLR_GPS gps; bool firstLocation = false; #endregion public TestGps() { InitializeComponent(); gps = new CLR_GPS(); gps.refreshLocation += gps_refreshLocation; gps.refreshTime += gps_refreshTime; gps.refreshDate += gps_refreshDate; //gps.refreshAltitude += new CLR_GPS.altitudeEventHandler(gps_refreshAltitude); gps.refreshSatellite += gps_refreshSatellite; gps.refreshAllNumber += gps_refreshAllNumber; gps.InitModule(); } #region Satellite Total void gps_refreshAllNumber(string num) { if (isClosed) { return; } Invoke(new portDataShow(showNumber), num); } void showNumber(string num) { textBoxAll.Text = num; } #endregion #region Refresh effective satellite void gps_refreshSatellite(string n) { if (isClosed) { return; } Invoke(new portDataShow(showSatellite), n); } void showSatellite(string n) { textBoxsatellite.Text = n; } #endregion #region refresh Altitude //void gps_refreshAltitude(string altitude) //{ // if (isClosed) // { // return; // } // this.Invoke(new portDataShow(showAltitude), altitude); //} //void showAltitude(string altitude) //{ // textBoxAltitude.Text = altitude; //} #endregion #region refresh date void gps_refreshDate(string date) { if (isClosed) { return; } Invoke(new portDataShow(showDate), date); } void showDate(string date) { textBoxDate.Text = date; } #endregion #region refresh time void gps_refreshTime(string time) { if (isClosed) { return; } Invoke(new portDataShow(showTime), time); } void showTime(string time) { textBoxTime.Text = time.Substring(0, 2) + ":" + time.Substring(2, 2) + ":" + time.Substring(4, 2); } #endregion #region refresh location void gps_refreshLocation(string Latitude, string Longitude, string status, bool isNorth, bool isEast, string time) { if (isClosed) { return; } Invoke(new LocationShow(showLocation), Latitude, Longitude, status, isNorth, isEast, time); } private void showLocation(string Latitude, string Longitude, string status, bool isNorth, bool isEast,string time) { if (!firstLocation) { firstLocation = true; endTime = DateTime.Now.Minute * 60 + DateTime.Now.Second; textBoxAccess.Text = Convert.ToString(DateTime.Now.TimeOfDay.ToString()); textBoxSpend.Text = Convert.ToString(endTime - beginTime); } textBoxLa.Text = Latitude; textBoxLo.Text = Longitude; } #endregion #region 窗体加载事件 判断操作系统是中文还是英文 进行控件赋值 private void MainForm_Load(object sender, EventArgs e) { int n = 0; if (isEnglish()) { n = 1; } labelDate.Text = TextDate[n]; labelTime.Text = TextTime[n]; labelLa.Text = TextLatitude[n]; labelLo.Text = TextLongitude[n]; labelAll.Text = TextSatelliteTotal[n]; labelUsed.Text = TextEffectiveSatellite[n]; //labelAltitude.Text = TextAltitude[n]; labelCurr.Text = TextCurr[n]; labelBegin.Text = TextBegin[n]; labelAccess.Text = TextAcees[n]; labelSpend.Text = TextSpend[n]; labelSecond.Text = TextSecond[n]; } #endregion #region 获取GPS相应信息 private void btnGet_Click(object sender, EventArgs e) { //gps.InitModule(); btnStop.Enabled = true; btnGet.Enabled = false; btnStop.Focus(); if (!gps.startReceive()) { MessageBox.Show("get data failure, the port is not open.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1); return; } isClosed = false; firstLocation = false; beginTime = System.DateTime.Now.Minute * 60 + DateTime.Now.Second; textBoxBeginTime.Text = Convert.ToString(DateTime.Now.TimeOfDay.ToString()); } #endregion #region 读取注册表信息,判断是不是英文操作系统 /// <summary> /// Read registry information, judge whether English OS 读取注册表信息,判断是不是英文操作系统 /// </summary> /// <returns></returns> public static bool isEnglish() { try { var RegKey = Registry.CurrentUser.OpenSubKey(@"ControlPanel\Appearance"); if ("Windows 标准" == RegKey.GetValue("Current").ToString()) return false; return true; } catch (Exception) { return true; } } #endregion #region 停止GPS接收 private void btnStop_Click(object sender, EventArgs e) { gps.stopReceive(); isClosed = true; btnGet.Enabled = true; btnStop.Enabled = false; btnGet.Focus(); } #endregion #region GPS下电操作 private void MainForm_Closed(object sender, EventArgs e) { gps.FreeModule(); } #endregion #region Interface language 界面语言 private string[] TextDate = new [] { "日期:", "Date:" }; private string[] TextTime = new [] { "UTC时间:", "UTC time:" }; private string[] TextLongitude = new [] { "经度:", "Longitude:" }; private string[] TextLatitude = new [] { "纬度", "Latitude:" }; private string[] TextSatelliteTotal =new []{"可视卫星数量:","Satellite Total:"}; private string[] TextEffectiveSatellite =new []{"可用卫星数量:","Effective number:"}; private string[] TextAltitude = new [] { "海拔:", "Altitude:" }; private string[] TextCurr = new [] { "当前时间等于UTC时间加上当地所属时区", "current time=UTC time +local time zone" }; private string[] TextBegin = new [] { "开始时间:", "Begin time:" }; private string[] TextAcees = new [] { "获取时间", "Access time:" }; private string[] TextSpend = new [] { "有效定位时间", "Spending time:" }; private string[] TextSecond = new string[] { "秒", "second" }; #endregion #region 关闭窗口按钮 private void buttonClosed_Click(object sender, EventArgs e) { if (btnStop.Enabled) { btnStop_Click(sender, e); } Close(); } #endregion }