虽然在.NET Framework中提供了串口通信类(SerialPort),但是该类是基于同步方式实现的串口通信,虽然也提供了事件通知方式接收数据,但是在实际使用过程中,感觉其效率与Visual C++实现的异步方式串口通信要低不少。
另外感觉.NET Framework提供的串口通信类,使用起来稍显复杂,步骤较多。我们软件编程中,都希望能够通过简单的接口调用实现我们所需要的功能,既可以提高编程的效率,也可以降低编程中出现的Bug。
本着简单易用的原则,这里采用C++/CLR的方式,对Windows API的串口函数进行了封装,提供了简单易用的接口,使用步骤简单,使用者无需对串口知识深入了解,知道基本串口参数知识就可以使用了。
具体接口如下:
接收串口数据的调用步骤为:
1) 设置串口初始化参数PortInitParams;
2) 打开串口Open;
3) 设置接收数据的代理函数SetDataRecvDelegate;
4) 使能接收数据EnableRead。
其中接收串口数据采用了辅助线程的方式接收串口数据,在C#中调用时,如果需要在控件上显示接收的数据,则需要采取一定的措施,否则软件运行时会报错。
发送串口数据的调用步骤比较简单:打开串口后,就可以调用Write方法发送串口数据。
另外感觉.NET Framework提供的串口通信类,使用起来稍显复杂,步骤较多。我们软件编程中,都希望能够通过简单的接口调用实现我们所需要的功能,既可以提高编程的效率,也可以降低编程中出现的Bug。
本着简单易用的原则,这里采用C++/CLR的方式,对Windows API的串口函数进行了封装,提供了简单易用的接口,使用步骤简单,使用者无需对串口知识深入了解,知道基本串口参数知识就可以使用了。
具体接口如下:
串口初始化结构体如下:
namespace AsyncPortNet
{
// 摘要:
// 串口初始参数
public struct PortInitParams
{
// 摘要:
// 波特率
public uint baudRate;
//
// 摘要:
// 数据位, Number of bits/byte, 4-8
public byte dataBits;
//
// 摘要:
// 流控制, 0-无, 1-软件, 2-硬件
public uint handshake;
//
// 摘要:
// 接收缓冲的大小, 字节数
public uint inBuffer;
//
// 摘要:
// 发送数据缓冲的大小, 字节数
public uint outBuffer;
//
// 摘要:
// 奇偶校验, 0-4=None,Odd,Even,Mark,Space
public byte parity;
//
// 摘要:
// 串口号
public ushort portNum;
//
// 摘要:
// 停止位, 0,1,2 = 1, 1.5, 2
public byte stopBits;
}
}
串口通信类接口如下:
namespace AsyncPortNet
{
// 摘要:
// 异步串口通讯类, 实现了简单的读写串口数据
public class AsyncPort : IDisposable
{
// 摘要:
// 构造函数
public AsyncPort();
// 摘要:
// 波特率
public uint BaudRate { get; set; }
//
// 摘要:
// 数据位, Number of bits/byte, 4-8
public byte DataBits { get; set; }
//
// 摘要:
// 流控制, 0-无, 1-软件, 2-硬件
public uint HandShake { get; set; }
//
// 摘要:
// 接收缓冲的大小, 字节数
public uint InBufferSize { get; set; }
//
// 摘要:
// 发送数据缓冲的大小, 字节数
public uint OutBufferSize { get; set; }
//
// 摘要:
// 奇偶校验, 0-4=None,Odd,Even,Mark,Space
public byte Parity { get; set; }
//
// 摘要:
// 串口号
public ushort PortNum { get; set; }
//
// 摘要:
// 停止位, 0,1,2 = 1, 1.5, 2
public byte StopBits { get; set; }
// 摘要:
// 获取组建的最后编译时间
//
// 返回结果:
// 最后编译时间的字符串
public string BuilTime();
//
// 摘要:
// 关闭串口
public void Close();
//
// 摘要:
// 析构函数
public override sealed void Dispose();
//
// 摘要:
// 使能接收数据
//
// 参数:
// bEnable:
// true-使能, false-不使能
public void EnableRead(bool bEnable);
//
// 摘要:
// 串口是否已经打开
//
// 返回结果:
// true-已经打开, false-没有打开
public bool IsOpen();
//
// 摘要:
// 打开串口
//
// 返回结果:
// 0-正常, 其它-错误代码
public uint Open();
//
// 摘要:
// 打开串口
//
// 参数:
// portInitParams:
// 串口初始化参数结构体
//
// 返回结果:
// 0-正常, 其它-错误代码
public uint Open(PortInitParams portInitParams);
//
// 摘要:
// 串口号是否存在
//
// 参数:
// portNum:
// 串口号
//
// 返回结果:
// true-存在, false-不存在
public bool PortIsExist(ushort portNum);
//
// 摘要:
// 设置接收数据的代理
//
// 参数:
// recvDelegate:
// 代理
public void SetDataRecvDelegate(AsyncPort.PortDataRecvDelegate recvDelegate);
//
// 摘要:
// 向串口写入数据
//
// 参数:
// buffer:
// 要写入串口的数据
public void Write(byte[] buffer);
// 摘要:
// 串口接收到数据的代理类型
//
// 参数:
// userData:
// 用户数据
//
// data:
// 串口接收到的数据
//
// portNum:
// 串口号
//
// 返回结果:
// 返回值
public delegate uint PortDataRecvDelegate(ulong userData, byte data, ushort portNum);
}
}
接收串口数据的调用步骤为:
1) 设置串口初始化参数PortInitParams;
2) 打开串口Open;
3) 设置接收数据的代理函数SetDataRecvDelegate;
4) 使能接收数据EnableRead。
其中接收串口数据采用了辅助线程的方式接收串口数据,在C#中调用时,如果需要在控件上显示接收的数据,则需要采取一定的措施,否则软件运行时会报错。
发送串口数据的调用步骤比较简单:打开串口后,就可以调用Write方法发送串口数据。