在C#开发中与硬件设备进行串口通信是非常常见的需求,比如对接工业传感器、扫码枪、单片机设备等场景都需要用到串口通信能力。C#官方提供了System.IO.Ports命名空间下的SerialPort类,封装了串口操作的底层逻辑,开发者不需要处理复杂的系统API调用,就能快速实现串口通信功能。

一、基础准备与串口参数说明
在使用SerialPort类之前,需要先引入对应的命名空间,串口通信涉及几个核心参数,这些参数需要和对接的硬件设备保持一致,否则会出现通信失败或者数据乱码的问题:
- 端口号:比如COM1、COM3,是系统识别到的串口名称
- 波特率:数据传输的速率,常见的有9600、115200等
- 数据位:每个数据帧的位数,通常是8位
- 停止位:数据帧结束的标识位,常见为1位
- 校验位:用于校验数据是否传输错误,常见为无校验、奇校验、偶校验
二、基础串口操作实现
1. 初始化串口并打开
首先需要在项目中引入System.IO.Ports命名空间,然后创建SerialPort实例并配置参数,最后调用Open方法打开串口:
using System;
using System.IO.Ports;
namespace SerialPortDemo
{
class Program
{
static void Main(string[] args)
{
// 创建串口实例
SerialPort serialPort = new SerialPort();
// 配置串口参数,需要和硬件设备保持一致
serialPort.PortName = "COM3"; // 端口号
serialPort.BaudRate = 9600; // 波特率
serialPort.DataBits = 8; // 数据位
serialPort.StopBits = StopBits.One; // 停止位
serialPort.Parity = Parity.None; // 校验位,无校验
try
{
// 打开串口
serialPort.Open();
Console.WriteLine("串口打开成功");
}
catch (Exception ex)
{
Console.WriteLine("串口打开失败:" + ex.Message);
}
}
}
}
2. 发送数据
串口发送数据支持发送字节数组和字符串两种形式,发送字符串时会按照指定的编码转换为字节数组再发送,默认编码是ASCII,中文场景需要指定为UTF8或者GBK:
// 发送字符串,指定编码为UTF8
string sendStr = "Hello SerialPort";
serialPort.Write(sendStr, 0, sendStr.Length);
// 发送字节数组
byte[] sendBytes = new byte[] { 0x01, 0x02, 0x03, 0x04 };
serialPort.Write(sendBytes, 0, sendBytes.Length);
三、数据接收与事件驱动
SerialPort类提供了DataReceived事件,当串口接收到数据时会自动触发该事件,不需要手动轮询读取数据,效率更高。需要注意事件触发在非UI线程,如果在WinForm或者WPF程序中更新UI,需要进行线程切换。
// 注册数据接收事件
serialPort.DataReceived += SerialPort_DataReceived;
// 数据接收事件处理方法
private static void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
// 读取接收到的字符串,使用UTF8编码
string receiveStr = sp.ReadExisting();
// 读取字节数组形式的数据
int bytesToRead = sp.BytesToRead;
byte[] receiveBytes = new byte[bytesToRead];
sp.Read(receiveBytes, 0, bytesToRead);
Console.WriteLine("接收到字符串:" + receiveStr);
Console.WriteLine("接收到字节数组:" + BitConverter.ToString(receiveBytes));
}
四、关闭串口与异常处理
使用完串口之后需要及时关闭并释放资源,避免端口被占用。同时串口通信过程中可能会出现端口被拔出、参数不匹配等异常,需要做好异常捕获处理:
try
{
if (serialPort != null && serialPort.IsOpen)
{
// 取消事件注册
serialPort.DataReceived -= SerialPort_DataReceived;
// 关闭串口
serialPort.Close();
// 释放资源
serialPort.Dispose();
Console.WriteLine("串口已关闭并释放资源");
}
}
catch (Exception ex)
{
Console.WriteLine("关闭串口时发生异常:" + ex.Message);
}
五、常见问题与解决方案
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 打开串口提示端口不存在 | 端口号填写错误,或者设备未连接 | 检查设备管理器中的端口号,确认硬件已正确连接 |
| 接收数据乱码 | 波特率、编码和硬件不一致 | 确认硬件的波特率参数,发送和接收使用相同的编码 |
| DataReceived事件不触发 | 硬件未发送数据,或者事件未正确注册 | 确认硬件正常发送数据,检查事件注册代码是否正确 |
注意:在WinForm程序中,DataReceived事件运行在后台线程,直接操作UI控件会抛出跨线程异常,需要使用Invoke方法切换到UI线程后再更新控件内容。
C#_SerialPort串口通信数据收发事件驱动异常处理修改时间:2026-07-19 10:42:27