在C#串口通信中,一发一收的场景,如何处理不同功能码的帧数据比较合理,代码结构好
在 C# 串口通信的一发一收场景里,处理不同功能码的帧数据可采用以下合理的代码结构,它能让代码更具可读性、可维护性和可扩展性。
实现思路
- 定义帧结构:创建一个类来表示通信帧,其中包含功能码、数据等信息。
- 功能码处理逻辑:使用字典或者
switch
语句来根据不同的功能码执行相应的处理逻辑。 - 数据接收与解析:在串口接收事件中解析接收到的数据,并根据功能码调用对应的处理方法。
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}");}
}