- 由于最近写了许多软件都需要调用到串口驱动,本来 C#自带的已经封装的挺好了,不过为了以后图省事,所以在C#串口驱动的基础上封装了一个类库,未来只要引用一个类库,用两行代码直接完成了串口的操作。
- 下面讲一下串口类库里面的内容以及调用方法。
- 串口类库调用方法:
首先,在解决方案中,添加“现有项目”,现有项目选择类库。
然后,在需要使用串口的项目中右键点击“引用”,选择“添加引用”,在项目中选择刚才添加的引用即可。
最后,在代码中添加下面这一行代码,即算引用成功。
SerialPortUtility mySp = new SerialPortUtility();
- 串口无非就4个功能:
1. 打开串口
打开串口前,需要配置好串口参数,如果没有配对参数的话,用try catch捕捉报错信息,就会提示你哪些参数没用配对,同理,用try catch也能捕捉到打开的串口 是否有异常等状况。
下面是类库代码:
/// <summary>
/// 设置 串口配置
/// </summary>
/// <param name="portName">串口号</param>
/// <param name="baudRate">波特率</param>
/// <param name="parity">校验位</param>
/// <param name="dataBits">数据位</param>
/// <param name="stopBits">停止位</param>
private void SetSerialPortConfig(string portName, int baudRate, int parity, int dataBits, int stopBits)
{
// 串口 参数设置
mySerialPort.PortName = portName;
mySerialPort.BaudRate = baudRate;
switch (parity)
{
case 0:
default:
mySerialPort.Parity = Parity.None;
break;
case 1:
mySerialPort.Parity = Parity.Odd;
break;
case 2:
mySerialPort.Parity = Parity.Even;
break;
case 3:
mySerialPort.Parity = Parity.Mark;
break;
case 4:
mySerialPort.Parity = Parity.Space;
break;
}
mySerialPort.DataBits = ((4 < dataBits) && (dataBits < 9)) ? dataBits : 8;
switch (stopBits)
{
case 0:
mySerialPort.StopBits = StopBits.None;
break;
case 1:
default:
mySerialPort.StopBits = StopBits.One;
break;
case 2:
mySerialPort.StopBits = StopBits.OnePointFive;
break;
case 3:
mySerialPort.StopBits = StopBits.Two;
break;
}
mySerialPort.ReadTimeout = -1;
mySerialPort.RtsEnable = true;
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceived);
// 串口 接收数据处理定时器 参数设置
SerialPortRecvTimer = new System.Timers.Timer();
SerialPortRecvTimer.Interval = 100;
SerialPortRecvTimer.AutoReset = false;
SerialPortRecvTimer.Elapsed += new ElapsedEventHandler(SPRecvTimer_Tick);
}
/// <summary>
/// 打开串口
/// </summary>
/// <param name="portName">串口号</param>
/// <param name="baudRate">波特率</param>
/// <param name="parity">校验位</param>
/// <param name="dataBits">数据位</param>
/// <param name="stopBits">停止位</param>
public void OpenSerialPort(string portName, int baudRate, int parity, int dataBits, int stopBits)
{
try
{
SetSerialPortConfig(portName, baudRate, parity, dataBits, stopBits);
mySerialPort.Open();
}
catch (System.Exception)
{
throw;
}
}
下面是调用类库方法的代码:
mySp.OpenSerialPort("COM2"/*串口号*/, 115200/*波特率*/, 0/*校验位*/, 8/*数据位*/, 1/*停止位*/);
2. 关闭串口
关闭串口之前只要判断下该串口是否打开过即可。
下面是类库代码:
/// <summary>
/// 关闭串口
/// </summary>
public void CloseSerialPort()
{
try
{
mySerialPort.Close();
}
catch (System.Exception)
{
throw;
}
}
下面是调用类库方法的代码:
mySp.CloseSerialPort();
3. 发送数据
下面是类库代码:
/// <summary>
/// 串口数据发送
/// </summary>
/// <param name="content"></param>
public void SendData(byte[] content)
{
try
{
mySerialPort.Write(content, 0, content.Length);
}
catch (System.Exception)
{
throw;
}
}
下面是调用类库方法的代码:
发送数据时,如果不是byte类型的话,需要进行一次格式转换。
mySp.SendData(new byte[] { 0x0D });
4. 接收数据
下面是类库代码:
/// <summary>
/// 串口接收数据 位置
/// </summary>
private static int pSerialPortRecv = 0;
/// <summary>
/// 缓存区大小的长度
/// 缓冲区可调大
/// (接收数据处理定时器 内接收数据量 小于下面设置的值即可)
/// </summary>
private static int byteLength = 40960;
/// <summary>
/// 串口接收字节 缓存区大小
/// </summary>
private byte[] byteSerialPortRecv = new byte[byteLength];
/// <summary>
/// 串口 接收数据处理定时器
/// </summary>
private Timer SerialPortRecvTimer;
/// <summary>
/// 广播 收到的数据 事件
/// </summary>
public event EventHandler<SerialPortRecvEventArgs> ReceivedDataEvent;
/// <summary>
/// 广播 收到的数据
/// </summary>
public class SerialPortRecvEventArgs : EventArgs
{
/// <summary>
/// 广播 收到的串口数据
/// </summary>
public readonly byte[] RecvData = new byte[byteLength];
/// <summary>
/// 收到数据 的 长度
/// </summary>
public readonly int RecvDataLength;
/// <summary>
/// 将 收到的数据 转化成 待广播的数据
/// </summary>
public SerialPortRecvEventArgs(byte[] recvData, int recvDataLength)
{
recvData.CopyTo(RecvData, 0);
RecvDataLength = recvDataLength;
}
}
/// <summary>
/// 数据处理定时器
/// 定时检查缓冲区是否有数据,如果有数据则将数据处理并广播。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SPRecvTimer_Tick(object sender, EventArgs e)
{
byte[] TemporaryData = new byte[byteLength];
int TemporaryDataLength = 0;
if (ReceivedDataEvent != null)
{
byteSerialPortRecv.CopyTo(TemporaryData, 0);
TemporaryDataLength = pSerialPortRecv;
ReceivedDataEvent.Invoke(this, new SerialPortRecvEventArgs(TemporaryData, TemporaryDataLength));
// 数据处理完后,将指针指向数据头,等待接收新的数据
pSerialPortRecv = 0;
}
}
/// <summary>
/// 数据接收事件
/// 串口收到数据后,关闭定时器,将收到的数据填入缓冲区,数据填入完毕后,开启定时器,等待下一次数据接收
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
SerialPortRecvTimer.Stop();
byte[] ReadBuf = new byte[mySerialPort.BytesToRead];
mySerialPort.Read(ReadBuf, 0, ReadBuf.Length);
ReadBuf.CopyTo(byteSerialPortRecv, pSerialPortRecv);
pSerialPortRecv += ReadBuf.Length;
SerialPortRecvTimer.Start();
}
catch (System.Exception)
{
throw;
}
}
下面是调用类库方法的代码:
下面相当于是订阅串口接收数据事件,这样一有消息就能接收到,打开串口操作前或后都能加,但是一定要加,不加的话,就没办法接收到消息。
// 订阅事件 可以放在 Form_Load 中 或者其他函数中,但必须执行
mySp.ReceivedDataEvent += new EventHandler<SerialPortUtility.SerialPortRecvEventArgs>(mySp_ReceivedDataEvent);
/// <summary>
/// 订阅接收数据的内容
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void mySp_ReceivedDataEvent(object sender, SerialPortUtility.SerialPortRecvEventArgs args)
{
// 数据内容
Console.Write(args.RecvData);
// 数据长度
Console.Write(args.RecvDataLength);
}
本项目源码CSDN下载地址:https://download.csdn.net/download/langwangak/11229685
本项目源码Github下载地址:https://github.com/Liu-YiZe/SerialPort_4NetFramework