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