基于FINS协议实现的C#欧姆龙PLC通信

简介: 基于FINS协议实现的C#欧姆龙PLC通信,包含串口/TCP双模式支持、FCS校验、内存区读写等核心功能

基于FINS协议实现的C#欧姆龙PLC通信,包含串口/TCP双模式支持、FCS校验、内存区读写等核心功能


一、核心代码结构

// 通信接口定义
public interface IFinsClient : IDisposable
{
   
    bool Connect();
    bool ReadMemory(string area, ushort address, ushort length, out byte[] data);
    bool WriteMemory(string area, ushort address, byte[] data);
    void Disconnect();
}

// 串口实现类
public class FinsSerialClient : IFinsClient
{
   
    private SerialPort _port;
    private const int FCS_OFFSET = 2; // FCS校验码起始位置

    public FinsSerialClient(string portName, int baudRate = 9600)
    {
   
        _port = new SerialPort(portName, baudRate, Parity.Even, 7, StopBits.Two);
        _port.Handshake = Handshake.None;
        _port.DataReceived += OnDataReceived;
    }

    public bool Connect()
    {
   
        try
        {
   
            _port.Open();
            SendCommand("STX@00FA0000000037ETX"); // 初始化握手命令
            return true;
        }
        catch (Exception ex)
        {
   
            Debug.WriteLine($"连接失败: {ex.Message}");
            return false;
        }
    }

    public bool ReadMemory(string area, ushort address, ushort length, out byte[] data)
    {
   
        string cmd = BuildReadCommand(area, address, length);
        SendCommand(cmd);
        var response = ReadResponse();
        return ParseReadResponse(response, out data);
    }

    private string BuildReadCommand(string area, ushort addr, ushort len)
    {
   
        var ms = new MemoryStream();
        ms.WriteByte(0x01); // 读命令
        ms.WriteByte((byte)GetAreaCode(area));
        WriteAddress(ms, addr);
        ms.WriteByte(0x00); // 高字节长度
        ms.WriteByte((byte)len);
        return Convert.ToBase64String(ms.ToArray());
    }

    private byte[] GetAreaCode(string area)
    {
   
        return area switch
        {
   
            "CIO" => 0x30, // CIO区代码
            "WR" => 0x33,  // WR区代码
            "HR" => 0x34,  // HR区代码
            "DM" => 0x35,  // DM区代码
            _ => throw new ArgumentException("无效的内存区域")
        };
    }

    private void WriteAddress(MemoryStream ms, ushort addr)
    {
   
        ms.WriteByte((byte)(addr >> 8));   // 高字节
        ms.WriteByte((byte)addr);          // 低字节
        ms.WriteByte((byte)(addr >> 8));   // 扩展高字节
        ms.WriteByte((byte)addr);          // 扩展低字节
    }

    // 其他方法实现...
}

// TCP实现类
public class FinsTcpClient : IFinsClient
{
   
    private TcpClient _client;
    private NetworkStream _stream;
    private readonly byte[] _header = {
    0x02, 0x46, 0x49, 0x4E, 0x53 }; // FINS头

    public bool Connect(string ip, int port = 9600)
    {
   
        _client = new TcpClient();
        _client.Connect(ip, port);
        _stream = _client.GetStream();
        return SendCommand("STX@00FA0000000037ETX");
    }
}

二、关键功能实现

1. FCS校验算法

private byte CalculateFCS(byte[] data)
{
   
    byte checksum = 0;
    foreach (var b in data.Skip(FCS_OFFSET)) // 跳过STX和长度字段
    {
   
        checksum ^= b;
    }
    return checksum;
}

// 带校验的帧构建
private byte[] BuildFrame(byte[] payload)
{
   
    using var ms = new MemoryStream();
    ms.WriteByte(0x02); // STX
    ms.WriteByte((byte)payload.Length); // 长度
    ms.Write(payload, 0, payload.Length);
    ms.WriteByte(CalculateFCS(payload));
    ms.WriteByte(0x03); // ETX
    return ms.ToArray();
}

2. 异步通信处理

public async Task<byte[]> ReadAsync(int timeoutMs = 5000)
{
   
    var buffer = new byte[4096];
    var cts = new CancellationTokenSource(timeoutMs);

    try
    {
   
        int bytesRead = await _stream.ReadAsync(buffer, 0, buffer.Length, cts.Token);
        return buffer.Take(bytesRead).ToArray();
    }
    catch (OperationCanceledException)
    {
   
        throw new TimeoutException("读取超时");
    }
}

3. 响应解析器

public bool ParseReadResponse(byte[] response, out byte[] data)
{
   
    if (response.Length < 10) 
    {
   
        data = null;
        return false;
    }

    // 校验FCS
    var receivedFcs = response;
    var calcFcs = CalculateFCS(response.Skip(2).Take(response.Length - 3).ToArray());

    if (receivedFcs != calcFcs)
    {
   
        Debug.WriteLine("FCS校验失败");
        data = null;
        return false;
    }

    // 提取数据段
    data = response.Skip(6).Take(response.Length - 8).ToArray();
    return true;
}

三、完整使用示例

using (var plc = new FinsSerialClient("COM3"))
{
   
    if (plc.Connect())
    {
   
        // 读取D100开始的2个字
        if (plc.ReadMemory("DM", 100, 2, out byte[] data))
        {
   
            ushort value = (ushort)(data[0] << 8 | data[1]);
            Console.WriteLine($"D100值: {value}");
        }

        // 写入CIO 200地址
        plc.WriteMemory("CIO", 200, new byte[] {
    0x01, 0x00 });
    }
}

四、工业级优化方案

1. 连接池管理

public class FinsConnectionPool
{
   
    private readonly ConcurrentBag<IFinsClient> _clients = new();
    private readonly object _lock = new();

    public IFinsClient GetClient()
    {
   
        if (_clients.TryTake(out var client))
            return client;

        return CreateNewClient();
    }

    private IFinsClient CreateNewClient()
    {
   
        var client = new FinsSerialClient("COM3");
        client.Connect();
        return client;
    }

    public void ReturnClient(IFinsClient client)
    {
   
        _clients.Add(client);
    }
}

2. 批量操作优化

public class BatchCommand
{
   
    private readonly List<byte[]> _commands = new();

    public void AddRead(string area, ushort addr, ushort len)
    {
   
        _commands.Add(BuildReadCommand(area, addr, len));
    }

    public byte[] GetBatchData()
    {
   
        using var ms = new MemoryStream();
        foreach (var cmd in _commands)
        {
   
            ms.Write(cmd, 0, cmd.Length);
        }
        return ms.ToArray();
    }
}

3. 异常处理策略

public class FinsExceptionHandler
{
   
    private readonly Dictionary<byte, Action<byte[]>> _handlers = new();

    public void RegisterHandler(byte errorCode, Action<byte[]> handler)
    {
   
        _handlers[errorCode] = handler;
    }

    public void HandleError(byte[] errorFrame)
    {
   
        var code = errorFrame[2]; // 错误码位置
        if (_handlers.TryGetValue(code, out var action))
        {
   
            action(errorFrame);
        }
        else
        {
   
            Debug.WriteLine($"未知错误码: {code:X2}");
        }
    }
}

五、调试与测试工具

1. 串口监控器

public class SerialMonitor
{
   
    private SerialPort _port;

    public void StartCapture(string portName)
    {
   
        _port = new SerialPort(portName);
        _port.DataReceived += (s, e) =>
        {
   
            var data = new byte[_port.BytesToRead];
            _port.Read(data, 0, data.Length);
            File.WriteAllBytes($"capture_{DateTime.Now:yyyyMMddHHmmss}.bin", data);
        };
        _port.Open();
    }
}

2. 帧分析工具

public static class FrameAnalyzer
{
   
    public static string AnalyzeFrame(byte[] frame)
    {
   
        if (frame.Length < 5) return "无效帧";

        var type = frame[0] switch
        {
   
            0x01 => "读命令",
            0x02 => "写命令",
            _ => "未知类型"
        };

        var address = (frame[2] << 8) | frame[3];
        return $"类型: {type}, 地址: {address:X4}, 长度: {frame[4]}";
    }
}

六、部署建议

  1. 硬件配置

    • 工业PC:研华AIMB-501(支持宽温运行)

    • 通信模块:欧姆龙CP1E PLC + FINS兼容适配器

  2. 安全配置

    // 启用加密通信
    _port.EncryptMode = SerialPortEncryptMode.AES256;
    _port.SetEncryptionKey("YourSecureKey123");
    
  3. 性能调优

    • 设置ReadBufferSize = 65536

    • 启用DoubleBuffered = true

参考代码 C#写的欧姆龙PLC通信库与源码 www.youwenfan.com/contentalh/112013.html

七、扩展功能实现

1. 数据监控看板

public class RealTimeMonitor
{
   
    private Chart _chart;

    public void UpdateData(byte[] data)
    {
   
        var value = BitConverter.ToInt16(data, 0);
        _chart.Series[0].Points.AddY(value);
        if (_chart.Series[0].Points.Count > 1000)
        {
   
            _chart.Series[0].Points.RemoveAt(0);
        }
    }
}

2. 自动重连机制

public class AutoReconnect
{
   
    private readonly IFinsClient _client;
    private readonly int _retryInterval = 5000;

    public AutoReconnect(IFinsClient client)
    {
   
        _client = client;
        Task.Run(CheckConnection);
    }

    private async Task CheckConnection()
    {
   
        while (true)
        {
   
            if (!_client.IsConnected)
            {
   
                Debug.WriteLine("尝试重连...");
                await Task.Delay(_retryInterval);
                _client.Connect();
            }
            await Task.Delay(1000);
        }
    }
}
相关文章
|
设计模式 前端开发 数据可视化
【第4期】一文了解React UI 组件库
【第4期】一文了解React UI 组件库
1105 0
|
10月前
|
缓存 网络协议 安全
基于C#实现欧姆龙PLC FINS/TCP通信
基于C#实现欧姆龙PLC FINS/TCP通信
|
2月前
|
人工智能 JSON 数据可视化
ComfyUI 搭建 AI 漫剧生产线:零代码 AI 漫剧视频工作流
2026年AI漫剧已成创作新主流!本文详解「Dify + ComfyUI」零代码组合:Dify作智能大脑(剧本生成、多Agent协作、结构化输出),ComfyUI当执行双手(本地高清图/视频生成、角色一致性强)。全流程自动化,一人日产多集,支持本地部署与隐私保护。(238字)
|
9月前
|
前端开发
关于宜搭轻享版产品调整及升级优惠活动的通知
钉钉宜搭拟于2026年起逐步退出轻享版业务,1月1日起停止新购,4月1日起停止续约。老用户可享专业版升级优惠,仅需补差价40%,应用数据无缝迁移,无功能损失,助力低代码能力升级。
4430 3
|
6月前
|
人工智能 IDE 开发工具
Visual Studio 2026 Enterprise 18.4.0 - 适用于 Windows 上 .NET 和 C++ 开发人员的最全面 IDE
Visual Studio 2026 Enterprise 18.4.0 - 适用于 Windows 上 .NET 和 C++ 开发人员的最全面 IDE
244 1
Visual Studio 2026 Enterprise 18.4.0 - 适用于 Windows 上 .NET 和 C++ 开发人员的最全面 IDE
|
7月前
|
人工智能 IDE 开发工具
Visual Studio 2026 Enterprise 18.3.0 Offline (2026 年 2 月更新)
Visual Studio 2026 Enterprise 18.3.0 Offline (2026 年 2 月更新) - 适用于 Windows 上 .NET 和 C++ 开发人员的最全面 IDE
697 1
Visual Studio 2026 Enterprise 18.3.0 Offline (2026 年 2 月更新)
|
6月前
|
人工智能 机器人 网络安全
三步,OpenClaw(Clawdbot)阿里云部署完成,拥有7×24小时AI助手
在AI智能体快速普及的2026年,OpenClaw(原Clawdbot、MoltBot)凭借“本地优先、强执行能力、开源免费”的核心优势,成为个人办公与轻量团队协作的必备工具——它不仅能像聊天机器人一样响应自然语言指令,更能真正“动手做事”,完成文件处理、信息查询、自动化协同、代码执行等各类任务,彻底解放重复劳动。而阿里云推出的OpenClaw专属一键部署方案,更是将复杂的部署流程简化至三步,无需专业技术储备,新手零基础也能快速完成搭建,依托阿里云稳定的基础设施,实现AI助手7×24小时在线、随时响应,无需担心本地设备关机导致服务中断。
589 7
|
9月前
|
人工智能 网络协议 开发者
无成本搭建 AI 画图神器!我以后再也不会手绘架构图了
小富带你零成本搭建AI画图神器!基于Next.js和开源项目next-ai-draw-io,结合Vercel免费部署,秒变AI绘图平台。输入文字自动生成可二次编辑的流程图、架构图,支持多模型,无需服务器,一键上线,写文档、画架构效率翻倍!
2355 1
|
9月前
|
JSON 安全 Java
6.鉴权
本文介绍基于Spring Security与JWT实现客户端Token认证方案,涵盖从登录生成Token到接口验签的完整流程。通过WebSecurityConfig配置安全规则,结合JWTLoginFilter与JWTAuthenticationFilter实现登录验证与请求拦截,利用TokenAuthenticationService完成JWT生成与解析。支持角色与权限控制,构建RBAC权限体系,保障Spring Boot应用安全。
|
监控 算法 数据挖掘
项目介绍:RQAlpha量化框架
RQAlpha是Python算法回测与交易框架,支持多证券类型,提供数据获取、策略开发、回测、实盘模拟及数据分析等全套解决方案,具备灵活配置、易用性及强大扩展性。
项目介绍:RQAlpha量化框架