当前位置:首页>>开发编程>>VS.NET>>新闻内容  
用C#读取GPS数据的基类
作者: 发布时间:2006-8-30 10:02:38 | 【字体:

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


文章来源:网络转载
·C#的支付宝Payto接口代码
·C#实现窗口最小化到系统托盘
·解密QQ的MsgEx.db消息文件格式
·QQ的TEA填充算法C#实现
·C#用Guid获取不规则的唯一值(标识)
·基于Windows Mobile 5.0的掌上天气预报设计
·C#下实现程序在线升级的方法
·C#发送Email邮件三种方法的总结
·C#格式化数值结果表(格式化字符串)
·教你用C#开发智能手机游戏:推箱子
 放生
 愚爱
 够爱
 触电
 白狐
 葬爱
 光荣
 画心
 火花
 稻香
 小酒窝
 下雨天
 右手边
 安静了
 魔杰座
 你不像她
 边做边爱
 擦肩而过
 我的答铃
 怀念过去
 等一分钟
 放手去爱
 冰河时代
 你的承诺
 自由飞翔
 原谅我一次
 吻的太逼真
 左眼皮跳跳
 做你的爱人
 一定要爱你
 飞向别人的床
 爱上别人的人
 感动天感动地
 心在跳情在烧
 玫瑰花的葬礼
 有没有人告诉你
 即使知道要见面
 爱上你是一个错
 最后一次的温柔
 爱上你是我的错
 怎么会狠心伤害我
 不是因为寂寞才想
 亲爱的那不是爱情
 难道爱一个人有错
 寂寞的时候说爱我