用C#读取GPS数据的基类

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-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;
   }
  }
}

在别的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();
   }
   #endregion

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值