在 C# 串口通信的一发一收场景里,处理不同功能码的帧数据可采用以下合理的代码结构,它能让代码更具可读性、可维护性和可扩展性。
实现思路
- 定义帧结构:创建一个类来表示通信帧,其中包含功能码、数据等信息。
- 功能码处理逻辑 :使用字典或者
switch
语句来根据不同的功能码执行相应的处理逻辑。 - 数据接收与解析:在串口接收事件中解析接收到的数据,并根据功能码调用对应的处理方法。
cs
using System;
using System.Collections.Generic;
using System.IO.Ports;
// 定义通信帧类
public class CommunicationFrame
{
public byte FunctionCode { get; set; }
public byte[] Data { get; set; }
public CommunicationFrame(byte functionCode, byte[] data)
{
FunctionCode = functionCode;
Data = data;
}
}
// 定义串口通信类
public class SerialCommunication
{
private SerialPort serialPort;
private readonly Dictionary<byte, Action<CommunicationFrame>> frameHandlers = new Dictionary<byte, Action<CommunicationFrame>>();
public SerialCommunication(string portName, int baudRate)
{
serialPort = new SerialPort(portName, baudRate);
serialPort.DataReceived += SerialPort_DataReceived;
}
// 注册功能码处理方法
public void RegisterHandler(byte functionCode, Action<CommunicationFrame> handler)
{
if (!frameHandlers.ContainsKey(functionCode))
{
frameHandlers.Add(functionCode, handler);
}
}
// 打开串口
public void Open()
{
if (!serialPort.IsOpen)
{
serialPort.Open();
}
}
// 关闭串口
public void Close()
{
if (serialPort.IsOpen)
{
serialPort.Close();
}
}
// 发送数据
public void Send(CommunicationFrame frame)
{
if (serialPort.IsOpen)
{
byte[] dataToSend = new byte[1 + frame.Data.Length];
dataToSend[0] = frame.FunctionCode;
Array.Copy(frame.Data, 0, dataToSend, 1, frame.Data.Length);
serialPort.Write(dataToSend, 0, dataToSend.Length);
}
}
// 数据接收处理
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
if (serialPort.BytesToRead > 0)
{
byte functionCode = (byte)serialPort.ReadByte();
int dataLength = serialPort.BytesToRead;
byte[] data = new byte[dataLength];
serialPort.Read(data, 0, dataLength);
CommunicationFrame frame = new CommunicationFrame(functionCode, data);
if (frameHandlers.TryGetValue(functionCode, out var handler))
{
handler(frame);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error receiving data: {ex.Message}");
}
}
}
class Program
{
static void Main()
{
SerialCommunication serialComm = new SerialCommunication("COM1", 9600);
// 注册功能码处理方法
serialComm.RegisterHandler(1, HandleFunctionCode1);
serialComm.RegisterHandler(2, HandleFunctionCode2);
serialComm.Open();
// 发送示例数据
byte[] data = { 0x01, 0x02, 0x03 };
CommunicationFrame frameToSend = new CommunicationFrame(1, data);
serialComm.Send(frameToSend);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
serialComm.Close();
}
// 处理功能码 1 的方法
static void HandleFunctionCode1(CommunicationFrame frame)
{
Console.WriteLine($"Received frame with function code 1. Data length: {frame.Data.Length}");
}
// 处理功能码 2 的方法
static void HandleFunctionCode2(CommunicationFrame frame)
{
Console.WriteLine($"Received frame with function code 2. Data length: {frame.Data.Length}");
}
}