c#讀取gps數據基類

用C#讀取GPS數據的基類

2007-9-30 網友評論 0 條 點擊進入論壇

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

  }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章