C#实现ModbusTCP从站(三)
C#实现ModbusTCP从站(三)
前言
- 【作者】:编程笔记in
- 【原文】:mp.weixin.qq.com/s/EerOuTF2HK72ykNHJS1duQ
- 本文描述如何使用C#原生的Socket类实现ModbusTCP从站功能。
- ModbusTCP从站是作为响应设备(服务器端)被动接收并处理主站(客户端)的请求,通过使用Socket创建从站服务,用于侦听主站(客户端)连接,获取请求及数据响应。
项目介绍
- 项目实现了线圈(Coils)和保持寄存器(Holding Registers)的数据临时缓存功能,其中线圈是2进制数据,寄存器是16位整形数据。所以可以创建bool数组(boo[])和ushort数组(ushort[])存储数据。
- 使用Socket接收发送,在接收数据后,按照Modbus的协议格式转换数据,再将转换后的数据发送回去,达到通讯效果。
- 下面是实现的数据处理功能。
1、处理客户端功能码:
- ① 处理线圈读取(功能码0x01)。
- ② 处理保持寄存器读取(功能码0x03)。
- ③ 处理线圈写入(功能码0x05)。
- ④ 处理寄存器写入(功能码0x06)。
- ⑤ 处理多线圈写入(功能码0x0F)。
- ⑥ 处理多寄存器写入(功能码0x10)。
2、实现功能:
创建设置和获取线圈和寄存器数据的方法,基本功能如(①②③④),方法是直接设置或获取数组的值,没有使用Modbus协议。属于测试功能,仅限测试时使用(正常情况不建议直接修改值)。
① 获取单个或多个线圈的值。
② 获取单个或多个寄存器的值。
③ 设置单个或多个线圈。
④ 设置单个或多个寄存器。
⑤ 支持多客户端连接。
⑥ 显示或隐藏请求报文。
⑦ 显示或隐藏相应报文。
⑧ 定时读取功能。
运行环境
- 操作系统:Windows11
- 编程软件:Visual Studio 2022
- Net版本:.Net Framework 4.8.0
预览
(一)运行效果
代码
(一)MainForm代码
- 界面代码大概如下,实现了基本的连接、读取、写入、是否显示报文功能(下面仅是基本的字段和方法 方法签名,完整内容文末自行下载)。
public partial class MainForm : Form
{
ModbusTcpSlave modbusTcpSlave;
ushort startAddress = 0;
ushort dataLength = 1;
Timer timerRead; public MainForm(){ InitializeComponent(); }
private void MainForm_Load(object sender, EventArgs e){}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e){}
private void Initialize(){}
private void TimerRead_Tick(object sender, EventArgs e){} #region 事件方法
#region 按钮事件
private void btn_Connect_Click(object sender, EventArgs e){}
private void btn_ReadData_Click(object sender, EventArgs e){}
private void btn_SendData_Click(object sender, EventArgs e){}
private void btn_ClearMessage_Click(object sender, EventArgs e){}
private void btn_ClearSendData_Click(object sender, EventArgs e){}
#endregion
private void ModbusTcpSlave_MessageCallabck(object sender, ModbusMessageEvents message){}
private void ModbusTcpSlave_RequestCallabck(object sender, ModbusMessageEvents message){}
private void ModbusTcpSlave_ResponseCallback(object sender, ModbusMessageEvents message){}
#endregion #region 控件状态更新
private void ControlStateUpdate(){}
private void checkBox_TimedRead_CheckedChanged(object sender, EventArgs e){}
#endregion #region 操作消息更新
private void MessageUpdate(string data, Color color, string appendText = null, int maxLineNum = 1000, bool isAppendTime = true){}
private void SetTextColor(RichTextBox rtb, int startIndex, int length, Color color){}
#endregion #region 参数变更
private void nudx_StartAddress_ValueChanged(object sender, EventArgs e){}
private void nudx_DataLength_ValueChanged(object sender, EventArgs e){}
private void cbx_FuncCode_SelectedIndexChanged(object sender, EventArgs e){}
#endregion
}
(二)ModbusTcpSlave代码
- 在这里声明创建从站用到的字段、属性、事件、及相关的方法,相关方法声明如下(下面仅是类的字段和方法,方法签名,完整内容文末自行下载)。
public class ModbusTcpSlave
{
#region 字段|属性|事件
public event EventHandler<ModbusMessageEvents> MessageCallback;
public event EventHandler<ModbusMessageEvents> RequestCallabck;
public event EventHandler<ModbusMessageEvents> ResponseCallback;
private int _port = 502;
private string _address;
private int unitId = 1;
private bool _isRunning;
private ushort[] _holdingRegisters;
private readonly int MaxDataCount = 65536;
private bool[] _coils;
private const int MaxConnections = 5;
public int ReceiveTimeout { get; private set; } = 3000;
private Thread listenerThread = null;
private Socket slaveSocket;
private Dictionary<string, Thread> clientThreadList;
public bool IsRunning { get => _isRunning; }
public string FuncCode { get; set; } = "01";
#endregion
#region 构造函数|对象参数初始化
public ModbusTcpSlave(string ipAddress = "127.0.0.1", int port = 502, byte unitId = 1){}
private void Initialize(){}
#endregion
#region 启动|停止
public void Start(){}
public void Stop(){}
private void ListenClient(){}
private void HandleClientConnect(object socket){}
#endregion
#region 数据转换
public static string ArrayToString<T>(T[] values, string sep = " "){}
public static string ArrayToHex<T>(T[] values, string sep = " ") where T : struct, IConvertible{}
public static T[] StringToArray<T>(string input, char sep = ','){}
public static T[] TryStringToArray<T>(string input, char sep = ','){}
private ushort[] ConvertRequestMessage(byte[] request){}
#endregion
#region 数据变更处理
private byte[] ProcessRequest(byte[] request, int length){}
private byte[] HandleReadCoils(byte[] request, ushort startAddress, ushort numberOfPoint){}
private byte[] HandleReadHoldingRegisters(byte[] request, ushort startAddress, ushort numberOfPoint){}
private byte[] HandleWriteSingleCoil(byte[] request, ushort address, ushort value){}
private byte[] HandleWriteSingleRegister(byte[] request, ushort address, ushort value){}
private byte[] HandleWriteMultipleCoils(byte[] request, ushort startAddress, ushort numberOfPoint){}
private byte[] HandleWriteMultipleRegisters(byte[] request, ushort startAddress, ushort numberOfPoint){}
private byte[] CreateErrorResponse(byte[] request, byte errorCode){}
#endregion
#region 数据变更处理-强制处理
public bool SetSingleCoils(ushort address, bool value){}
public bool SetSingleRegister(ushort address, ushort value){}
public bool SetMultipleCoils(ushort startAddress, bool[] data){}
public bool SetMultipleRegister(ushort startAddress, ushort[] data){}
public bool[] GetCoils(ushort address, ushort numberOfPoint){}
public ushort[] GetRegisters(ushort address, ushort numberOfPoint){}
#endregion
#region 回调触发方法
private void OnMessageCallabck(ModbusMessageEvents message){}
private void OnRequestCallabck(ModbusMessageEvents message){}
private void OnResponseCallabck(ModbusMessageEvents message){}
#endregion
}
结语
通过该项目学习如何使用C# 实现ModbuTCP通讯的从站功能,之前写过使用Socket实现TCP通讯,个人理解从站是在此基础上做了数据保存处理、在发送接收数据时遵从Modbus协议,最后根据情况将数据格式转换,更多功能会在后续添加,写文章是用于记录和分享、在写的过程中加深印象。
项目源码 gitee.com/incodenotes/csharp-modbus
如果你觉得这篇文章对你有帮助,不妨点个赞再走呗!
如有其他疑问,欢迎评论区留言讨论!
也可以加入微信公众号 [编程笔记in] ,一起交流学习!
C#实现ModbusTCP从站(三)的更多相关文章
- S7-200和S7-300profibus-DP通信
一.S7-200CN的cup可以通过EM277接入DP网络 二.CPU315-2DP做主站,S7-200CUP做从站 三. 通信题目 四.硬件组态 1.主站的DP组态,地址为2 2.EM277作为从站 ...
- Modbus 指令
本节内容: 一.S7-1200 作为Modbus RTU 主站 二.S7-1200 作为Modbus RTU 从站 三.S7-1200 作为Modbus RTU 主站 S7-1200 作为Modbus ...
- ModbusTCP协议
简介 Modbus由MODICON公司于1979年开发,是一种工业现场总线协议标准.1996年施耐德公司推出基于以太网TCP/IP的Modbus协议:ModbusTCP. Modbus协议是一项应用层 ...
- Java实现ModbusTCP通信
一个项目,需要用Java实现使用ModbusTCP和硬件设备通信 资料 代码下载 本文的代码和仿真软件:蓝奏云下载 官网资料 Modbus官网 Modbus协议 Modbus技术资源 MODBUS T ...
- 基于Python的ModbusTCP客户端实现
Modbus协议是由Modicon公司(现在的施耐德电气Schneider Electric)推出,主要建立在物理串口.以太网TCP/IP层之上,目前已经成为工业领域通信协议的业界标准,广泛应用在工业 ...
- 从MySQL到ORM(三):连接、存储过程和用户权限
一.联结表 数据仍使用前文中的数据. 1.子查询 作为子查询的SELECT语句只能查询单个列.企图检索多个列将返回错误. -- 作为查询条件使用 -- 查看TNT2订单对应的客户ip(order表) ...
- IoTClient开发3 - ModBusTcp协议客户端实现
前言 进过前面两章的介绍,今天开始正式的实战. 进制转换 很多朋友对于进制转换可能是在刚学计算机的时候有接触,后来做高级语言开发可能就慢慢忘记了.我们做工控开发的时候需要经常进行进制转换,这里和大家一 ...
- 组态DP主站与标准从站的步骤
分为以下几个部分 第一:组态DP主站与标准从站 分为以下几个步骤 步骤1: 将标准从站ET200 ,ET200在硬件组态软件界面的最右边的PROFIBUS-DP界面里面, PROFIBUS-DP里面是 ...
- 【新阁教育】台达DVP-ES3 ModbusTCP通信案例
本文主要针对台达DVP-ES3系列PLC,实现上位机与PLC之间的ModbusTCP通信. 一.硬件说明 DVP-ES3 系列为高阶应用可编程控制器, CPU 内置4 组高速计数器输入.4组轴输出(脉 ...
- 常用 Gulp 插件汇总 —— 基于 Gulp 的前端集成解决方案(三)
前两篇文章讨论了 Gulp 的安装部署及基本概念,借助于 Gulp 强大的 插件生态 可以完成很多常见的和不常见的任务.本文主要汇总常用的 Gulp 插件及其基本使用,需要读者对 Gulp 有一个基本 ...
随机推荐
- 使用crewai创建属于你自己的AI团队
crewai介绍 CrewAI 是一个用于协调自主 AI 代理的前沿框架. CrewAI 允许你创建 AI 团队,其中每个代理都有特定的角色.工具和目标,协同工作以完成复杂任务. 把它想象成组建你的梦 ...
- IGM机器人维修的关键环节
在现代科技领域,机器人已经成为不可或缺的一部分,它们广泛应用于各个行业,包括制造业.服务业.医疗.科研等.对于任何机器人来说,定期的维护和修理都是必不可少的.这不仅可以确保机器人正常工作,还可以延长其 ...
- Arduino语法--数据类型
Arduino与C语言类似,有多种数据类型.数据类型在数据结构中的定义是一个值的集合,以及定义在这个值集上的一组操作,各种数据类型需要在特定的地方使用.一般来说,变量的数据类型决定了如何将代表这些值的 ...
- mysql扫描全表更新状态部分失败
1. mysql排序问题 一直以为mysql是按照主键排序的,实则排序和主键没有关系(不使用 order by 子句). 然后从 stackoverflow 上查了一下,找到了以下的回答: 没有默认的 ...
- 在 Intel Ultra AI PC 设备上使用 OpenVINO™ C# API本地部署YOLOv11与YOLOv12
最新的英特尔 酷睿 Ultra 处理器(第二代)让我们能够在台式机.移动设备和边缘中实现大多数 AI 体验,将 AI 加速提升到新水平,在 AI 时代为边缘计算提供动力.英特尔 酷睿 Ultra ...
- Python装饰器:套层壳我变得更强了!
Python装饰器:套层壳我变得更强了 Python装饰器:套层壳我变得更强了 关于作用域和闭包可以聊点什么? 什么是作用域 什么是闭包 装饰器:套层壳我变得更强了 参考资料 昨天阅读了<Pyt ...
- 分布式锁—2.Redisson的可重入锁
大纲 1.Redisson可重入锁RedissonLock概述 2.可重入锁源码之创建RedissonClient实例 3.可重入锁源码之lua脚本加锁逻辑 4.可重入锁源码之WatchDog维持加锁 ...
- Manjora配置记录
22/9/12 目前的启动项有3:Windows Boot Manager.Manjaro.UEFI OS.其中UEFI OS 和 Manjaro 进入后内容相同:Windows下检测不到Manjar ...
- 实现Windows之间(win10)的桌面连接的三步走方法
实现Windows之间(win10)的远程桌面连接的三步走方法 目录 目录 实现Windows之间(win10)的远程桌面连接的三步走方法 目录 环境 step1:打开两台Windows电脑的 ...
- Flask快速入门1
因为新换了一个工作,项目使用了Flask框架技术,需要快速学习下,学过Django这个重量级的框架基础后,再去学习Flask框架相对还是容易的. 当然入门基础容易,要深入理解还是要慢慢花时间深耕练习使 ...