通用串口通信类

  以前串口通信一直用AxInterop.MSCommLib第三方串口通信类,但是发现那个东西用着很麻烦,因为需要设置ActiveX控件的持久状态OcxState,这个东西又蛋疼的一般在Winform的Designer里面,随意调整一下界面的布局,那个OcxState的设定就不见了。。。还有个蛋疼的地方就是打开和关闭串口需要比较久的时间。

  于是我就想要自己写一个串口通信类,就叫做SerialCommunication。

  首先需要一些DllImport

[DllImport("kernel32.dll")]
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 
    );
[DllImport("kernel32.dll")]
private static extern bool GetCommState(
    int hFile, // handle to communications device 
    ref Dcb lpDcb // device-control block 
    );
//[DllImport("kernel32.dll")]
//private static extern bool BuildCommDCB(
//    string lpDef, // device-control string 
//    ref DCB lpDcb // device-control block 
//    );
[DllImport("kernel32.dll")]
private static extern bool SetCommState(
    int hFile, // handle to communications device 
    ref Dcb lpDcb // device-control block 
    );
//[DllImport("kernel32.dll")]
//private static extern bool GetCommTimeouts(
//    int hFile, // handle to comm device 
//    ref CommTimeouts lpCommTimeouts // time-out values 
//    );
[DllImport("kernel32.dll")]
private static extern bool SetCommTimeouts(
    int hFile, // handle to comm device 
    ref CommTimeouts lpCommTimeouts // time-out values 
    );
[DllImport("kernel32.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("kernel32.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("kernel32.dll")]
private static extern bool CloseHandle(
    int hObject // handle to object 
    );
//[DllImport("kernel32.dll")]
//private static extern uint GetLastError();

  然后需要一些struct

[StructLayout(LayoutKind.Sequential)]
public struct CommTimeouts
{
    public UInt32 ReadIntervalTimeout;
    public UInt32 ReadTotalTimeoutMultiplier;
    public UInt32 ReadTotalTimeoutConstant;
    public UInt32 WriteTotalTimeoutMultiplier;
    public UInt32 WriteTotalTimeoutConstant;
}
[StructLayout(LayoutKind.Sequential)]
public struct Dcb
{
    public Int32 DCBlength;
    public Int32 BaudRate;
    public Int32 PackedValues;
    public Int16 wReserved;
    public Int16 XonLim;
    public Int16 XoffLim;
    public Byte ByteSize;
    public Byte Parity;
    public Byte StopBits;
    public Byte XonChar;
    public Byte XoffChar;
    public Byte ErrorChar;
    public Byte EofChar;
    public Byte EvtChar;
    public Int16 wReserved1;
}
[StructLayout(LayoutKind.Sequential)]
public struct Overlapped
{
    public UIntPtr Internal;
    public UIntPtr InternalHigh;
    public UInt32 Offset;
    public UInt32 OffsetHigh;
    public IntPtr hEvent;
}

  最后实现开关读写串口即可。开串口只需打开串口,设置串口两步操作,打开串口可能会失败,原因一般是该串口没有设备连接或者正在被其他设备使用中,设置串口也有可能会失败,原因一般是设置的参数不正确或者不够。关串口只需要执行CloseHandle即可

public void Open()
{
    // OPEN THE COMM PORT. 
    _hComm = CreateFile("COM" + PortNum, GenericRead | GenericWrite, 0, 0, OpenExisting, 0, 0);
    // IF THE PORT CANNOT BE OPENED, BAIL OUT. 
    if (_hComm == InvalidHandleValue)
    {
		throw (new Exception("Port Open Failure"));
    }
    CommTimeouts ctoCommPort = new CommTimeouts { ReadTotalTimeoutConstant = ReadTimeout };
    if (!SetCommTimeouts(_hComm, ref ctoCommPort))
    {
		throw (new Exception("Bad Timeout Settings"));
    }
    Dcb dcb = new Dcb();
    GetCommState(_hComm, ref dcb);
    dcb.BaudRate = BaudRate;
    dcb.Parity = Parity;
    dcb.ByteSize = ByteSize;
    dcb.StopBits = StopBits;
    if (!SetCommState(_hComm, ref dcb))
    {
		throw (new Exception("Bad Com Settings"));
    }
}
public void Close()
{
    if (_hComm != InvalidHandleValue)
    {
		CloseHandle(_hComm);
    }
}

  读串口执行ReadFile即可,可以在调用的地方开一个线程不断的读串口,不过需要考虑效率问题。写串口执行WriteFile即可,每次读、写串口不需要先关闭再打开串口,那样的话也会浪费效率,但是若串口号或者串口配置修改了,则需要关闭并重新打开串口。

  串口通信类源码

  

转载于:https://www.cnblogs.com/hambert/p/3392779.html

/* --------------------------------------------------------------- 文件名称:SmartMComDll.h 说 明:声明串口DLL函数 作 者:温子祺 创建时间:2010-08-06 联系方式:wenziqi@hotmail.com 博 客:http://www.cnblogs.com/wenziqi/ 小 组:http://group.ednchina.com/2748/ 官 网:www.smartmcu.com --------------------------------------------------------------- */ #ifdef SMARTMCOMDLL_EXPORTS #define SMARTMCOMDLL_API __declspec(dllexport) #else #define SMARTMCOMDLL_API __declspec(dllimport) #endif #ifdef __cplusplus extern "C" { #endif /***************************************************** *函数名称:Init *输 入:portnr 端口号 baud 波特率 parity 校验方式 databits 数据位 stopbits 停止位 *输 出:TRUE/FALSE *功 能:初始化串口 *示 例: BOOL b=Init(1,9600,NOPARITY,8,ONESTOPBIT); ******************************************************/ SMARTMCOMDLL_API extern BOOL Init(UINT portnr, UINT baud, UINT parity, UINT databits, UINT stopbits); /***************************************************** *函数名称:Close *输 入:无 *输 出:TRUE/FALSE *功 能:关闭串口 *示 例: BOOL b=Close(); ******************************************************/ SMARTMCOMDLL_API extern BOOL Close(void); /***************************************************** *函数名称:Send *输 入:pSendBytes 发送数据缓冲区 unSendLength 发送数据长度 *输 出:成功发送的字节数 *功 能:串口发送数据 *示 例: UINT8 buf[3]={0x01,0x02,0x03} UINT b=Send(buf,3); ******************************************************/ SMARTMCOMDLL_API extern UINT Send(UCHAR *pSendBytes,UINT unSendLength); /***************************************************** *函数名称:Recv *输 入:pRecvBytes 接收数据缓冲区 unRecvLength 接收数据长度 *输 出:成功接收的字节数 *功 能:串口接收数据 *示 例: UINT8 buf[3]; UINT b=Recv(buf,3); ******************************************************/ SMARTMCOMDLL_API extern UINT Recv(UCHAR *pRecvBytes,UINT unRecvLength); #ifdef __cplusplus } #endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值