程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> 用C#讀取GPS數據的基類(適用於wince操作系統)

用C#讀取GPS數據的基類(適用於wince操作系統)

編輯:關於C#

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 u
    int GENERIC_READ = 0x80000000;

    private const u
    int 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 u
      int 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,
    // 要打開的串口名稱
    u
    int 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 u
    int 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 ) )
      {
        //u
        int 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中讀取的數據中,找出想要的數據
      ///GPs
      string原始字符串,
      ///strFind要查找的內容,X:經度,Y:緯度,T:時間,V:速度,是數字從1開始,即以“,”分隔的位置
      ///返回查找到指定位置的字符串
      string handerStr="$GPRMC";
      //GPS串頭
      int findHander=strGPS.IndexOf( handerStr );
      //看是否含有GPS串頭
      if ( findHander<0 )
      {
        return "-1";
      }
      else
      {
        strGPS=strGPS.Sub
        string( 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.Sub
      string( 4,2 )+"-"+strDate.Sub
      string( 2,2 )+"-"+strDate.Sub
      string( 0,2 );

      string TT=Convert.ToString( Convert.ToInt32( strTime.Sub
      string( 0,2 ) ) )+":"+strTime.Sub
      string( 2,2 )+":"+strTime.Sub
      string( 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.Sub
        string( 0,2 ) );
        double sDegree2=Convert.ToDouble( DegreeMinutes.Sub
        string( 2,DegreeMinutes.Length-2 ) );

        string sTmp=Convert.ToString( sDegree2/60 );
        sDegree2=Convert.ToDouble( sTmp.Sub
        string( 0,sTmp.Length ) );
        sDegree2=sDegree2/10000;
        sDegree=Convert.ToString( sDegree1+sDegree2 );
        if( sDegree.Length>11 )
        sDegree=sDegree.Sub
        string( 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.Sub
        string( 0,3 ) );
        double sMinute2=Convert.ToDouble( DegreeMinutes.Sub
        string( 3,DegreeMinutes.Length-2 ) );

        string sTmp=Convert.ToString( sMinute2/60 );
        sMinute2=Convert.ToDouble( sTmp.Sub
        string( 0,sTmp.Length ) );
        sMinute2=sMinute2/10000;
        sMinute=Convert.ToString( sMinute1+sMinute2 );
        if( sMinute.Length>10 )
        sMinute=sMinute.Sub
        string( 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 ComPo
int )
{
  ss_port.PortNum = ComPo
  int;
  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( );
}
#endregion

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved