串口通訊可以引出kernel32.dll中的API來操作,相關源碼如下:using System;using System.Runtime.InteropServices; namespace Telehome.GSM{/// <summary>/// *********************** ...
串口通訊可以引出kernel32.dll中的API來操作,相關源碼如下:
using System;
using System.Runtime.InteropServices;
namespace Telehome.GSM
{
/// <summary>
/// ************************************************************************************
///
/// Function: 連接,斷開串口;發送,接收串口數據,使用kernel32.dll中相關串口操作
/// 函數對COM口進行操作
///
/// Author: Telehome.Hzyong
///
/// DateTime: 2005-11-20
///
/// ************************************************************************************
/// </summary>
public class CommPort
{
/// <summary>
/// 埠名稱(COM1,COM2...COM4...)
/// </summary>
public string PortNum;
/// <summary>
/// 波特率9600
/// </summary>
public int BaudRate;
/// <summary>
/// 數據位4-8
/// </summary>
public byte ByteSize;
/// <summary>
/// 奇偶校驗0-4=no,odd,even,mark,space
/// </summary>
public byte Parity;
/// <summary>
/// 停止位
/// </summary>
public byte StopBits; // 0,1,2 = 1, 1.5, 2
/// <summary>
/// 超時長
/// </summary>
public int ReadTimeout;
/// <summary>
/// COM口句柄
/// </summary>
private int hComm = -1;
/// <summary>
/// 串口是否已經打開
/// </summary>
public bool Opened = false;
/// <summary>
/// WINAPI常量,寫標誌
/// </summary>
private const uint GENERIC_READ = 0x80000000;
/// <summary>
/// WINAPI常量,讀標誌
/// </summary>
private const uint GENERIC_WRITE = 0x40000000;
/// <summary>
/// WINAPI常量,打開已存在
/// </summary>
private const int OPEN_EXISTING = 3;
/// <summary>
/// WINAPI常量,無效句柄
/// </summary>
private const int INVALID_HANDLE_VALUE = -1;
/// <summary>
/// 設備控制塊結構體類型
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct DCB
{
/// <summary>
/// DCB長度
/// </summary>
public int DCBlength;
/// <summary>
/// 指定當前波特率
/// </summary>
public int BaudRate;
/// <summary>
/// 指定是否允許二進位模式
/// </summary>
public int fBinary;
/// <summary>
/// 指定是否允許奇偶校驗
/// </summary>
public int fParity;
/// <summary>
/// 指定CTS是否用於檢測發送控制,當為TRUE是CTS為OFF,發送將被掛起。
/// </summary>
public int fOutxCtsFlow;
/// <summary>
/// 指定CTS是否用於檢測發送控制
/// </summary>
public int fOutxDsrFlow;
/// <summary>
/// DTR_CONTROL_DISABLE值將DTR置為OFF, DTR_CONTROL_ENABLE值將DTR置為ON, DTR_CONTROL_HANDSHAKE允許DTR"握手"
/// </summary>
public int fDtrControl;
/// <summary>
/// 當該值為TRUE時DSR為OFF時接收的位元組被忽略
/// </summary>
public int fDsrSensitivity;
/// <summary>
/// 指定當接收緩衝區已滿,並且驅動程式已經發送出XoffChar字元時發送是否停止。
/// TRUE時,在接收緩衝區接收到緩衝區已滿的位元組XoffLim且驅動程式已經發送出
/// XoffChar字元中止接收位元組之後,發送繼續進行。 FALSE時,在接收緩衝區接
/// 收到代表緩衝區已空的位元組XonChar且驅動程式已經發送出恢複發送的XonChar之
/// 後,發送繼續進行。XOFF continues Tx
/// </summary>
public int fTXContinueOnXoff;
/// <summary>
/// TRUE時,接收到XoffChar之後便停止發送接收到XonChar之後將重新開始 XON/XOFF
/// out flow control
/// </summary>
public int fOutX;
/// <summary>
/// TRUE時,接收緩衝區接收到代表緩衝區滿的XoffLim之後,XoffChar發送出去接收
/// 緩衝區接收到代表緩衝區空的XonLim之後,XonChar發送出去 XON/XOFF in flow control
/// </summary>
public int fInX;
/// <summary>
/// 該值為TRUE且fParity為TRUE時,用ErrorChar 成員指定的字元代替奇偶校驗錯誤
/// 的接收字元 enable error replacement
/// </summary>
public int fErrorChar;
/// <summary>
/// eTRUE時,接收時去掉空(0值)位元組 enable null stripping
/// </summary>
public int fNull;
/// <summary>
/// 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
/// </summary>
public int fRtsControl;
/// <summary>
/// TRUE時,有錯誤發生時中止讀和寫操作 abort on error
/// </summary>
public int fAbortOnError;
/// <summary>
/// 未使用
/// </summary>
public int fDummy2;
/// <summary>
/// 標誌位
/// </summary>
public uint flags;
/// <summary>
/// 未使用,必須為0
/// </summary>
public ushort wReserved;
/// <summary>
/// 指定在XON字元發送這前接收緩衝區中可允許的最小位元組數
/// </summary>
public ushort XonLim;
/// <summary>
/// 指定在XOFF字元發送這前接收緩衝區中可允許的最小位元組數
/// </summary>
public ushort XoffLim;
/// <summary>
/// 指定埠當前使用的數據位
/// </summary>
public byte ByteSize;
/// <summary>
/// 指定埠當前使用的奇偶校驗方法,可能為:EVENPARITY,MARKPARITY,NOPARITY,ODDPARITY 0-4=no,odd,even,mark,space
/// </summary>
public byte Parity;
/// <summary>
/// 指定埠當前使用的停止位數,可能為:ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS 0,1,2 = 1, 1.5, 2
/// </summary>
public byte StopBits;
/// <summary>
/// 指定用於發送和接收字元XON的值 Tx and Rx XON character
/// </summary>
public char XonChar;
/// <summary>
/// 指定用於發送和接收字元XOFF值 Tx and Rx XOFF character
/// </summary>
public char XoffChar;
/// <summary>
/// 本字元用來代替接收到的奇偶校驗發生錯誤時的值
/// </summary>
public char ErrorChar;
/// <summary>
/// 當沒有使用二進位模式時,本字元可用來指示數據的結束
/// </summary>
public char EofChar;
/// <summary>
/// 當接收到此字元時,會產生一個事件
/// </summary>
public char EvtChar;
/// <summary>
/// 未使用
/// </summary>
public ushort wReserved1;
}
/// <summary>
/// 串口超時時間結構體類型
/// </summary>
[StructLayout(LayoutKind.Sequential)]
private struct COMMTIMEOUTS
{
public int ReadIntervalTimeout;
public int ReadTotalTimeoutMultiplier;
public int ReadTotalTimeoutConstant;
public int WriteTotalTimeoutMultiplier;
public int WriteTotalTimeoutConstant;
}
/// <summary>
/// 湓出緩衝區結構體類型
/// </summary>
[StructLayout(LayoutKind.Sequential)]
private struct OVERLAPPED
{
public int Internal;
public int InternalHigh;
public int Offset;
public int OffsetHigh;
public int hEvent;
}
/// <summary>
/// 打開串口
/// </summary>
/// <param name="lpFileName">要打開的串口名稱</param>
/// <param name="dwDesiredAccess">指定串口的訪問方式,一般設置為可讀可寫方式</param>
/// <param name="dwShareMode">指定串口的共用模式,串口不能共用,所以設置為0</param>
/// <param name="lpSecurityAttributes">設置串口的安全屬性,WIN9X下不支持,應設為NULL</param>
/// <param name="dwCreationDisposition">對於串口通信,創建方式只能為OPEN_EXISTING</param>
/// <param name="dwFlagsAndAttributes">指定串口屬性與標誌,設置為FILE_FLAG_OVERLAPPED(重疊I/O操作),指定串口以非同步方式通信</param>
/// <param name="hTemplateFile">對於串口通信必須設置為NULL</param>
[DllImport("kernel32.dll")]
private static extern int CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode,
int lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile);
/// <summary>
/// 得到串口狀態
/// </summary>
/// <param name="hFile">通信設備句柄</param>
/// <param name="lpDCB">設備控制塊DCB</param>
[DllImport("kernel32.dll")]
private static extern bool GetCommState(int hFile, ref DCB lpDCB);
/// <summary>
/// 建立串口設備控制塊
/// </summary>
/// <param name="lpDef">設備控制字元串</param>
/// <param name="lpDCB">設備控制塊</param>
[DllImport("kernel32.dll")]
private static extern bool BuildCommDCB(string lpDef, ref DCB lpDCB);
/// <summary>
/// 設置串口狀態
/// </summary>
/// <param name="hFile">通信設備句柄</param>
/// <param name="lpDCB">設備控制塊</param>
[DllImport("kernel32.dll")]
private static extern bool SetCommState(int hFile, ref DCB lpDCB);
/// <summary>
/// 讀取串口超時時間
/// </summary>
/// <param name="hFile">通信設備句柄</param>
/// <param name="lpCommTimeouts">超時時間</param>
[DllImport("kernel32.dll")]
private static extern bool GetCommTimeouts(int hFile, ref COMMTIMEOUTS lpCommTimeouts);
/// <summary>
/// 設置串口超時時間
/// </summary>
/// <param name="hFile">通信設備句柄</param>
/// <param name="lpCommTimeouts">超時時間</param>
[DllImport("kernel32.dll")]
private static extern bool SetCommTimeouts(int hFile, ref COMMTIMEOUTS lpCommTimeouts);
/// <summary>
/// 讀取串口數據
/// </summary>
/// <param name="hFile">通信設備句柄</param>
/// <param name="lpBuffer">數據緩衝區</param>
/// <param name="nNumberOfBytesToRead">多少位元組等待讀取</param>
/// <param name="lpNumberOfBytesRead">讀取多少位元組</param>
/// <param name="lpOverlapped">溢出緩衝區</param>
[DllImport("kernel32.dll")]
private static extern bool ReadFile(int hFile, byte[] lpBuffer, int nNumberOfBytesToRead,
ref int lpNumberOfBytesRead, ref OVERLAPPED lpOverlapped);
/// <summary>
/// 寫串口數據
/// </summary>
/// <param name="hFile">通信設備句柄</param>
/// <param name="lpBuffer">數據緩衝區</param>
/// <param name="nNumberOfBytesToWrite">多少位元組等待寫入</param>
/// <param name="lpNumberOfBytesWritten">已經寫入多少位元組</param>
/// <param name="lpOverlapped">溢出緩衝區</param>
[DllImport("kernel32.dll")]
private static extern bool WriteFile(int hFile, byte[] lpBuffer, int nNumberOfBytesToWrite,
ref int lpNumberOfBytesWritten, ref OVERLAPPED lpOverlapped);
[DllImport("kernel32.dll", SetLastError=true)]
private static extern bool FlushFileBuffers(int hFile);
[DllImport("kernel32.dll", SetLastError=true)]
private static extern bool PurgeComm(int hFile, uint dwFlags);
/// <summary>
/// 關閉串口
/// </summary>
/// <param name="hObject">通信設備句柄</param>
[DllImport("kernel32.dll")]
private static extern bool CloseHandle(int hObject);
/// <summary>
/// 得到串口最後一次返回的錯誤
/// </summary>
[DllImport("kernel32.dll")]
private static extern uint GetLastError();
/// <summary>
/// 建立與串口的連接
/// </summary>
public void Open()
{
DCB dcbCommPort = new DCB();
COMMTIMEOUTS ctoCommPort = new COMMTIMEOUTS();
// 打開串口
hComm = CreateFile(PortNum ,GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if(hComm == INVALID_HANDLE_VALUE)
{
return;
}
// 設置通信超時時間
GetCommTimeouts(hComm, ref ctoCommPort);
ctoCommPort.ReadTotalTimeoutConstant = ReadTimeout;
ctoCommPort.ReadTotalTimeoutMultiplier = 0;
ctoCommPort.WriteTotalTimeoutMultiplier = 0;
ctoCommPort.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(hComm, ref ctoCommPort);
// 設置串口
GetCommState(hComm, ref dcbCommPort);
dcbCommPort.fOutxCtsFlow = 524800;
dcbCommPort.BaudRate = BaudRate;
dcbCommPort.flags = 0;
dcbCommPort.flags |= 1;
if (Parity > 0)
{
dcbCommPort.flags |= 2;
}
dcbCommPort.Parity = Parity;
dcbCommPort.ByteSize = ByteSize;
dcbCommPort.StopBits = StopBits;
dcbCommPort.fOutxCtsFlow = 524800;
if (!SetCommState(hComm, ref dcbCommPort))
{
return;
}
Opened = true;
}
/// <summary>
/// 關閉串口,結束通訊
/// </summary>
public void Close()
{
if (hComm != INVALID_HANDLE_VALUE)
{
CloseHandle(hComm);
}
}
/// <summary>
/// 讀取串口返回的數據
/// </summary>
/// <param name="NumBytes">數據長度</param>
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);
OutBytes = new byte[BytesRead];
Array.Copy(BufBytes, OutBytes, BytesRead);
return OutBytes;
}
else
{
return new byte [0];
}
}
/// <summary>
/// 清空COM口緩衝區數據
/// </summary>
/// <returns></returns>
public bool ClearPortData()
{
bool result = false;
if (hComm != INVALID_HANDLE_VALUE)
{
result = PurgeComm(hComm, 0);
}
return result;
}
/// <summary>
/// 向串口寫數據
/// </summary>
/// <param name="WriteBytes">數據數組</param>
public bool Write(byte[] WriteBytes)
{
bool result;
if (hComm != INVALID_HANDLE_VALUE)
{
OVERLAPPED ovlCommPort = new OVERLAPPED();
int BytesWritten = 0;
WriteFile(hComm, WriteBytes, WriteBytes.Length, ref BytesWritten, ref ovlCommPort);
result = true;
}
else
{
result = false;
}
return result;
}
}
}
轉自