引用kernel32.dll中的API來進行串口通訊


串口通訊可以引出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;
}
}
}

轉自

https://www.xuebuyuan.com/841503.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM