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