科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件用C#读取GPS数据的基类

用C#读取GPS数据的基类

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

用C#读取GPS数据的基类

来源:soft6 2008年5月22日

关键字: gps 读取 C# Windows

  • 评论
  • 分享微博
  • 分享邮件
using System;

  using System.Runtime.InteropServices;

  using System.Text;

  namespace BaseStationPDA

  {

  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-3));

  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;

  }

  }

  }

  在别的class中调用时如Frmlogoin(是通过一个时间控件来循环的)

  public class Frmlogin : System.Windows.Forms.Form

  {

  private GPS ss_port=new GPS();

  }

  #region 读取GPS

  private void opengps(string ComPoint)

  {

  ss_port.PortNum = ComPoint;

  ss_port.BaudRate = 4800;

  ss_port.ByteSize = 8;

  ss_port.Parity = 0;

  ss_port.StopBits = 1;

  ss_port.ReadTimeout = 1000;

  try

  {

  if (ss_port.Opened)

  {

  ss_port.Close();

  ss_port.Open();

  timer1.Enabled=true;

  }

  else

  {

  ss_port.Open(); //打开串口

  timer1.Enabled=true;

  }

  }

  catch

  {

  // MessageBox.Show("读取GPS错误!" ,"系统提示");

  }

  }

  private void timer1_Tick(object sender, System.EventArgs e)

  {

  if (ss_port.Opened)

  gpsread();

  else

  ss_port.Open(); //打开串口

  }

  private void gpsread()

  {

  byte[] aa=ss_port.Read(512);

  string gpsinfo =System.Text.Encoding.ASCII.GetString(aa,0,aa.Length);

  GetParam.GpsLongitude=ss_port.GetGPS(gpsinfo,"X");

  GetParam.GpsLatitude=ss_port.GetGPS(gpsinfo,"Y");

  GetParam.GpsSpeed=ss_port.GetGPS(gpsinfo,"V");

  GetParam.GpsTime=ss_port.GetGPS(gpsinfo,"T");

  if(GetParam.GpsLongitude=="-1")

  GetParam.GpsState="0";

  if(GetParam.GpsLongitude=="V" && GetParam.GpsLatitude=="V")

  GetParam.GpsState="0";

  if(GetParam.GpsLongitude!="-1" && GetParam.GpsLongitude!="V")

  GetParam.GpsState="1";

  GetParam.GpsLongitude=(GetParam.GpsLongitude=="V") ? "0" : GetParam.GpsLongitude;

  GetParam.GpsLatitude=(GetParam.GpsLatitude=="V") ? "0" : GetParam.GpsLatitude;

  GetParam.GpsSpeed=(GetParam.GpsSpeed=="V") ? "0" : GetParam.GpsSpeed;

  GetParam.GpsTime=(GetParam.GpsTime=="V") ? "0" :GetParam.GpsTime;

  }

  private void GpsClose()

  {

  timer1.Enabled=false;

  if (ss_port.Opened)

  ss_port.Close();

  }

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章