当前位置: 首页 > news >正文

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

基于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); // STXms.WriteByte((byte)payload.Length); // 长度ms.Write(payload, 0, payload.Length);ms.WriteByte(CalculateFCS(payload));ms.WriteByte(0x03); // ETXreturn 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;}// 校验FCSvar 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/contentcnr/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);}}
}
http://www.jsqmd.com/news/370856/

相关文章:

  • 2026 企业专属知识库部署厂商推荐:跨部门知识打通、AI 赋能型方案商 - 品牌2025
  • FreeRTOS信号量使用详解
  • 2026 澳门科技大学申请机构推荐:三大专业升学规划机构优选报告! - 深度智识库
  • 2026年知识库部署实力厂商推荐 :企业级、AI 大模型、私有化、本地化部署服务商全覆盖 - 品牌2025
  • 【计算机毕业设计案例】基于springboot的快递管理软件管理系统基于springboot的快递业务管理系统(程序+文档+讲解+定制)
  • 【计算机毕业设计案例】基于springboot的校园二手物品推荐系统基于java+springboot+vue+mysql的校园闲置物品交易系统(程序+文档+讲解+定制)
  • 2026年成都留学申请机构权威推荐:电子科技大学学子专属指南 - 深度智识库
  • 全生命周期无忧!2026 AED(自动体外除颤器)品牌厂家推荐排行 智能管理/全周期服务/多规格适配 - 极欧测评
  • 实习生:我用一个 LLM 模型实现了 RAG 的 embedding 和 generation 全部功能
  • 2026 年 AI 知识库部署方案商推荐:大模型对接、语义检索、智能问答一站式服务商 - 品牌2025
  • 多机系统短路故障后时域仿真技术在电气工程领域的奇妙应用
  • 音频比特率设置多少最好?320kbps 真的比 128kbps 好很多吗
  • 软件神器 --- U盘烧录工具 之 rufus
  • 2026年低分上统招本科申请机构推荐:成都海学云帆教育领衔创新实践 - 深度智识库
  • Linux基础——IO性能测试及IOPS计算方法
  • AI元人文:圆融具身
  • Java毕设项目推荐-基于springboot的线上教学平台面向新工科课程线上教学辅助平台【附源码+文档,调试定制服务】
  • Java毕设项目推荐-基于springboot的校园二手物品推荐系统校园二手物品置换系统设计与实现【附源码+文档,调试定制服务】
  • 策马扬鞭迎新春|时序数据库 IoTDB 陪你稳稳过年
  • 资质合规优先!2026 AED(自动体外除颤器)品牌厂家推荐排行 长效耐用/智能管控/多场景适配 - 极欧测评
  • Java计算机毕设之基于springboot的面向新工科课程线上教学辅助平台线上教学平台(完整前后端代码+说明文档+LW,调试定制等)
  • Java计算机毕设之基于JAVA的人才招聘系统的设计与实现基于springboot的城市人才招聘系统的设计与实现(完整前后端代码+说明文档+LW,调试定制等)
  • 考生必看!2026主治医师3位靠谱授课老师盘点,听对课少走1年弯路 - 医考机构品牌测评专家
  • Linux基础——IOPS计算方法
  • 镇江本地生活代运营测评 三十六行镇江分公司实力解析 - 野榜数据排行
  • 2026年主治医师备考指南:5大金牌讲师课程风格深度解析,选对老师通关无忧! - 医考机构品牌测评专家
  • 2026年质量好的燕麦磨面机/莜麦磨面机精选供应商推荐口碑排行 - 品牌宣传支持者
  • 2026年知名的三合一陶瓷衬板/复合耐磨陶瓷衬板哪家专业制造厂家实力参考 - 品牌宣传支持者
  • 2026年净水行业白皮书:高标准水处理技术评测与选型战略指南 - 水业策论
  • 一行命令搞定!用 FFmpeg 按指定码率压缩视频