在C#串口通信中,一发一收的场景,如何处理不同功能码的帧数据比较合理,代码结构好

在 C# 串口通信的一发一收场景里,处理不同功能码的帧数据可采用以下合理的代码结构,它能让代码更具可读性、可维护性和可扩展性。

实现思路

  1. 定义帧结构:创建一个类来表示通信帧,其中包含功能码、数据等信息。
  2. 功能码处理逻辑 :使用字典或者switch语句来根据不同的功能码执行相应的处理逻辑。
  3. 数据接收与解析:在串口接收事件中解析接收到的数据,并根据功能码调用对应的处理方法。
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}");
    }
}
    
相关推荐
云烟成雨TD16 小时前
Spring AI Alibaba 1.x 系列【6】ReactAgent 同步执行 & 流式执行
java·人工智能·spring
小O的算法实验室16 小时前
2026年ASOC,基于深度强化学习的无人机三维复杂环境分层自适应导航规划方法,深度解析+性能实测
算法·无人机·论文复现·智能算法·智能算法改进
于慨16 小时前
Lambda 表达式、方法引用(Method Reference)语法
java·前端·servlet
swg32132116 小时前
Spring Boot 3.X Oauth2 认证服务与资源服务
java·spring boot·后端
gelald16 小时前
SpringBoot - 自动配置原理
java·spring boot·后端
殷紫川16 小时前
深入理解 AQS:从架构到实现,解锁 Java 并发编程的核心密钥
java
一轮弯弯的明月16 小时前
贝尔数求集合划分方案总数
java·笔记·蓝桥杯·学习心得
chenjingming66616 小时前
jmeter线程组设置以及串行和并行设置
java·开发语言·jmeter
殷紫川16 小时前
深入拆解 Java volatile:从内存屏障到无锁编程的实战指南
java
eddieHoo17 小时前
查看 Tomcat 的堆内存参数
java·tomcat