以下的这个类代码是没有问题,但是有一个问题,我怎么才能知道当前COM口的状态啊,有没有数据到了啊?要不然我调用的时候只能放在一个timer里,麻烦,消耗系统资源!各位,能把下面代码加上事件通知函数不?请帮帮忙!
using System;
using System.Runtime.InteropServices;
namespace SerialPort
{
public class SerialPort
{
#region 申明要引用的和串口调用有关的API
//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; 
private const int MAXBLOCK = 4096; private const uint PURGE_TXABORT = 0x0001;  // Kill the pending/current writes to the comm port.
private const uint PURGE_RXABORT = 0x0002;  // Kill the pending/current reads to the comm port.
private const uint PURGE_TXCLEAR = 0x0004;  // Kill the transmit queue if there.
private const uint PURGE_RXCLEAR = 0x0008;  // Kill the typeahead buffer if there.
       
[StructLayout(LayoutKind.Sequential)] 
private struct DCB  

//taken from c struct in platform sdk  
public int DCBlength;           // sizeof(DCB)  
public int BaudRate;            // current baud rate  
public int fBinary;          // binary mode, no EOF check  
public int fParity;          // enable parity checking  
public int fOutxCtsFlow;      // CTS output flow control  
public int fOutxDsrFlow;      // DSR output flow control  
public int fDtrControl;       // DTR flow control type  
public int fDsrSensitivity;   // DSR sensitivity  
public int fTXContinueOnXoff; // XOFF continues Tx  
public int fOutX;          // XON/XOFF out flow control  
public int fInX;           // XON/XOFF in flow control  
public int fErrorChar;     // enable error replacement  
public int fNull;          // enable null stripping  
public int fRtsControl;     // RTS flow control  
public int fAbortOnError;   // abort on error  
public int fDummy2;        // reserved  
public ushort wReserved;          // not currently used  
public ushort XonLim;             // transmit XON threshold  
public ushort XoffLim;            // transmit XOFF threshold  
public byte ByteSize;           // number of bits/byte, 4-8  
public byte Parity;             // 0-4=no,odd,even,,space  
public byte StopBits;           // 0,1,2 = 1, 1.5, 2  
public char XonChar;            // Tx and Rx XON character  
public char XoffChar;           // 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;  
} [StructLayout(LayoutKind.Sequential)]
private struct COMSTAT
{
/*public int fCtsHold;
public int fDsrHold;
public int fRlsdHold;
public int fXoffHold;
public int fXoffSent;
public int fEof;
public int fTxim;
public int fReserved;
public int cbInQue;
public int cbOutQue;*/
// Should have a reverse, i don't know why!!!!!
public int cbOutQue;
public int cbInQue;
public int fReserved;
public int fTxim;
public int fEof;
public int fXoffSent;
public int fXoffHold;
public int fRlsdHold;
public int fDsrHold;
public int fCtsHold;  
}
#if FULLFRAMEWORK
  [DllImport("kernel32")] 
  private static extern int CreateFile( 
   string lpFileName,                         // file name 
   uint dwDesiredAccess,                      // access mode 
   int dwShareMode,                          // share mode 
   int lpSecurityAttributes, // SD 
   int dwCreationDisposition,                // how to create 
   int dwFlagsAndAttributes,                 // file attributes 
   int hTemplateFile                        // handle to template file 
   );
#else
[DllImport("coredll")]
private static extern int CreateFile( 
string lpFileName,                         // file name 
uint dwDesiredAccess,                      // access mode 
int dwShareMode,                          // share mode 
int lpSecurityAttributes, // SD 
int dwCreationDisposition,                // how to create 
int dwFlagsAndAttributes,                 // file attributes 
int hTemplateFile                        // handle to template file 
);
#endif
#if FULLFRAMEWORK
  [DllImport("kernel32")] 
  private static extern bool GetCommState( 
   int hFile,  // handle to communications device 
   ref DCB lpDCB    // device-control block 
   );   
#else
[DllImport("coredll")] 
private static extern bool GetCommState( 
int hFile,  // handle to communications device 
ref DCB lpDCB    // device-control block 
);
#endif
#if FULLFRAMEWORK
  [DllImport("kernel32")] 
  private static extern bool BuildCommDCB( 
   string lpDef,  // device-control string 
   ref DCB lpDCB     // device-control block 
   ); 
#else
[DllImport("coredll")] 
private static extern bool BuildCommDCB( 
string lpDef,  // device-control string 
ref DCB lpDCB     // device-control block 
);
#endif
#if FULLFRAMEWORK
  [DllImport("kernel32")] 
  private static extern bool SetCommState( 
   int hFile,  // handle to communications device 
   ref DCB lpDCB    // device-control block 
   );
#else
[DllImport("coredll")] 
private static extern bool SetCommState( 
int hFile,  // handle to communications device 
ref DCB lpDCB    // device-control block 
);
#endif
#if FULLFRAMEWORK
  [DllImport("kernel32")] 
  private static extern bool GetCommTimeouts( 
   int hFile,                  // handle to comm device 
   ref COMMTIMEOUTS lpCommTimeouts  // time-out values 
   );
#else
[DllImport("coredll")] 
private static extern bool GetCommTimeouts( 
int hFile,                  // handle to comm device 
ref COMMTIMEOUTS lpCommTimeouts  // time-out values 
);
#endif
#if FULLFRAMEWORK
  [DllImport("kernel32")]    
  private static extern bool SetCommTimeouts( 
   int hFile,                  // handle to comm device 
   ref COMMTIMEOUTS lpCommTimeouts  // time-out values 
   );
#else
[DllImport("coredll")]    
private static extern bool SetCommTimeouts( 
int hFile,                  // handle to comm device 
ref COMMTIMEOUTS lpCommTimeouts  // time-out values 
);
#endif
#if FULLFRAMEWORK
  [DllImport("kernel32")] 
  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 
   );
#else
[DllImport("coredll")] 
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 
);
#endif//代码接下一楼

解决方案 »

  1.   

    #if FULLFRAMEWORK
      [DllImport("kernel32")] 
      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 
       ); 
    #else
    [DllImport("coredll")] 
    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 
    );
    #endif
    #if FULLFRAMEWORK
      [DllImport("kernel32")] 
      private static extern bool CloseHandle( 
       int hObject   // handle to object 
       );
    #else
    [DllImport("coredll")] 
    private static extern bool CloseHandle( 
    int hObject   // handle to object 
    );
    #endif
    #if FULLFRAMEWORK
      [DllImport("kernel32")]
      private static extern bool ClearCommError(
       int hFile,     // handle to file
       ref int lpErrors,
       ref COMSTAT lpStat
      );
    #else
    [DllImport("coredll")]
    private static extern bool ClearCommError(
    int hFile,     // handle to file
    ref int lpErrors,
    ref COMSTAT lpStat
    );
    #endif
    #if FULLFRAMEWORK
      [DllImport("kernel32")]
      private static extern bool PurgeComm(
       int hFile,     // handle to file
       uint dwFlags
       );
    #else
    [DllImport("coredll")]
    private static extern bool PurgeComm(
    int hFile,     // handle to file
    uint dwFlags
    );
    #endif
    #if FULLFRAMEWORK
      [DllImport("kernel32")]
      private static extern bool SetupComm(
       int hFile,
       int dwInQueue,
       int dwOutQueue
      );
    #else
    [DllImport("coredll")]
    private static extern bool SetupComm(
    int hFile,
    int dwInQueue,
    int dwOutQueue
    );
    #endif
    #endregion // SerialPort的成员变量
    private int hComm = INVALID_HANDLE_VALUE;
    private bool bOpened = false; public bool Opened
    {
    get
    {
    return bOpened;
    }
    }
      
    /// <summary>
    ///串口的初始化函数
    ///lpFileName  端口名
    ///baudRate   波特率
    ///parity   校验位
    ///byteSize   数据位
    ///stopBits   停止位
    /// <summary>
    public  bool OpenPort(string lpFileName,int baudRate,byte parity, byte byteSize, byte stopBits)  
    {    
    // OPEN THE COMM PORT.   
    hComm = CreateFile(lpFileName ,GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); 
    // IF THE PORT CANNOT BE OPENED, BAIL OUT. 
    if(hComm == INVALID_HANDLE_VALUE)  

    return false;
    } SetupComm(hComm, MAXBLOCK, MAXBLOCK);
           
    // SET THE COMM TIMEOUTS.
    COMMTIMEOUTS ctoCommPort = new COMMTIMEOUTS();
    GetCommTimeouts(hComm,ref ctoCommPort); 
    ctoCommPort.ReadIntervalTimeout = Int32.MaxValue;
    ctoCommPort.ReadTotalTimeoutConstant = 0; 
    ctoCommPort.ReadTotalTimeoutMultiplier = 0; 
    ctoCommPort.WriteTotalTimeoutMultiplier = 10; 
    ctoCommPort.WriteTotalTimeoutConstant = 1000;   
    SetCommTimeouts(hComm,ref ctoCommPort); 
           
    // SET BAUD RATE, PARITY, WORD SIZE, AND STOP BITS. 
    // THERE ARE OTHER WAYS OF DOING SETTING THESE BUT THIS IS THE EASIEST. 
    // IF YOU WANT TO LATER ADD CODE FOR OTHER BAUD RATES, REMEMBER 
    // THAT THE ARGUMENT FOR BuildCommDCB MUST BE A POINTER TO A STRING. 
    // ALSO NOTE THAT BuildCommDCB() DEFAULTS TO NO HANDSHAKING. 
    DCB dcbCommPort = new DCB(); 
    dcbCommPort.DCBlength = Marshal.SizeOf(dcbCommPort); 
    GetCommState(hComm, ref dcbCommPort); 
    dcbCommPort.BaudRate = baudRate; 
    dcbCommPort.Parity = parity; 
    dcbCommPort.ByteSize = byteSize; 
    dcbCommPort.StopBits = stopBits; 
    SetCommState(hComm, ref dcbCommPort);  PurgeComm(hComm, PURGE_RXCLEAR | PURGE_RXABORT);
    PurgeComm(hComm, PURGE_TXCLEAR | PURGE_TXABORT);
             
    bOpened = true; 
    return true;
    } // 关闭串口
    public bool ClosePort()  

    if (hComm == INVALID_HANDLE_VALUE)  
    {
    return false;
    }
       
    if (CloseHandle(hComm))
    {
    hComm = INVALID_HANDLE_VALUE;
    bOpened = false;
    return true;
    }
    else
    {
    return false;
    }
    } // 往串口写数据
    public bool WritePort(byte[] WriteBytes)  

    if (hComm == INVALID_HANDLE_VALUE)  

    return false;
    } COMSTAT ComStat = new COMSTAT();
    int dwErrorFlags = 0; ClearCommError(hComm, ref dwErrorFlags, ref ComStat);
    if (dwErrorFlags != 0)
    PurgeComm(hComm, PURGE_TXCLEAR | PURGE_TXABORT); OVERLAPPED ovlCommPort = new OVERLAPPED(); 
    int BytesWritten = 0; 
    return WriteFile(hComm, WriteBytes, WriteBytes.Length, ref BytesWritten, ref ovlCommPort);       
    }
      
    // 从串口读数据
    public bool ReadPort(int NumBytes, ref byte[] commRead)  

    if (hComm == INVALID_HANDLE_VALUE)  
    {
    return false;
    }
       
    COMSTAT ComStat = new COMSTAT();
    int dwErrorFlags = 0; ClearCommError(hComm, ref dwErrorFlags, ref ComStat);
    if (dwErrorFlags != 0)
    PurgeComm(hComm, PURGE_RXCLEAR | PURGE_RXABORT);
        
    if (ComStat.cbInQue > 0)
    {
    OVERLAPPED ovlCommPort = new OVERLAPPED(); 
    int BytesRead = 0; 
    return ReadFile(hComm, commRead, NumBytes, ref BytesRead, ref ovlCommPort);
    }
    else
    {
    return false;
    }

    }
    }
      

  2.   

    我顶!没人看吗?是不是代码量太大?那我就说下作用:
    就是一个串口通讯类,我在MSDN上只是看不明白API函数,WaitSingleObject这些东西的意思,我是想怎么能的把C#这个,基于事件驱动的机制溶合进来,这样当串口有数据的时候就会自动执行回调函数,那样我就不需要用while去轮询串口了!这样也就不必要占用更多的系统资源!请精通此道的帮看看!谢谢
      

  3.   

    楼主,能不能把上面的那个kernel32.dll文件发一份给我,我也在做这个,但少了文件没法测试,先谢谢了
      

  4.   

    敢问海岛先生,你所用的系统是什么?
    kernel32.dll Windows NT4.0以上都有的
      

  5.   

    LZ提出的问题很好,串口我也做过一点,但像LZ提出的这样问题的确很难解决,如果不想用一个监视线程去监视口,那就需要一个中断服务去做,具体如何实现我就不知道了,有没有好的方法,高人解答,呵呵