C#使用NModbus4库创建Modbus TCP Slave(服务器)简单示例

news2024/11/15 11:24:58

本文续上篇Codesys—标准库ModbusTCP Master(客户端)配合C#的NModbus4库的通讯示例

链接:https://blog.csdn.net/wushangwei2019/article/details/136375234?spm=1001.2014.3001.5501

上篇描述在Codesys端的Modbus TCP Master(客户端)的设备添加、IO映射、通讯简单展示等方面,本文记录PC端C#利用NModbus4通讯库创建Modbus TCP Slave(服务器)的方法。

注:本文只记录如何使用NModbus4的部分功能,程序结构较为简单,并不适用于项目工程。

本文分以下几个步骤分享NModbus4的使用:

1.添加NModbus4库

2.ModbusTcpSlave从站的创建

3.事件订阅

4.通讯示例

界面附加显示功能:

1.在收到客户端报文的事件后,将会在信息提示框中显示报文内容,报文内容不包含CRC;在服务器写入完成后,将会在信息提示框中显示写入完成的报文内容。

2.在服务器线程中,获取已连接的客户端的IP地址以及端口号信息,并在最底下显示出来。

软件界面如下,本文针对左侧服务器(从站)端:

1.添加NModbus4库 

菜单栏点击【工具】-》【NuGet包管理器】-》【管理解决方案的NuGet程序包】

弹出以下画面,搜索【NModbus4】 ,选择需要安装的项目,并点击右下角的【安装】即可。

在程序中添加如下代码:

using Modbus.Data;
using Modbus.Device;
using Modbus.Extensions.Enron;

 2.使用TcpListener创建服务器

核心代码:

listener = new TcpListener(IPAddress.Parse(textBox2.Text), Convert.ToInt32(textBox3.Text));
listener.Start();
slave = ModbusTcpSlave.CreateTcp(1, listener);
slave.DataStore = DataStoreFactory.CreateDefaultDataStore(); 

slave.Listen();

解析:

1.TcpListener,用于创建服务器,需要输入参数待创建服务器的【IP地址】和【端口号】。

2.ModbusTcpSlave.CreateTcp方法,用于创建ModbusTCP Slave从站,创建后的从站对象为slave。

3.DataStoreFactory.CreateDefaultDataStore()方法,用于清除Modbus TCP Slave的数据存储区,寄存器区值全部写0。

4.slave.Listen()方法,Modbus TCP Slave开始监听请求,我的理解是有客户端连接后,Slave开始响应客户端的报文,此方法应该放在有客户端连接后再使用较好,但在此处调用也能正常运行。


            try
            {
                listener = new TcpListener(IPAddress.Parse(textBox2.Text), Convert.ToInt32(textBox3.Text));
                listener.Start();
                slave = ModbusTcpSlave.CreateTcp(1, listener);
                slave.DataStore = DataStoreFactory.CreateDefaultDataStore();
                WriteInfo("创建服务器成功!" + "线程ID:" + Thread.CurrentThread.ManagedThreadId + "\r\n");
                //订阅数据到达事件,不能获取具体接收到的报文
                //slave.DataStore.DataStoreWrittenTo += DataStoreWrittenToHandle;
                //订阅接收到报文请求事件,可以打印接收到的报文
                slave.ModbusSlaveRequestReceived += ModbusSlaveRequestReceivedHandle;
                //订阅接收到写入完成事件,可以打印写入完成响应
                slave.WriteComplete += WriteCompleteHandle;
                slave.Listen();
                isServerCreated = true;
                WriteInfo("服务器创建成功!" +  "\r\n");
                count2 = 0;
            }
            catch(Exception ex)
            {
                count2++;
                 WriteInfo("创建服务器失败!" + "失败次数:"+count2.ToString()+ "\r\n");
                isServerCreated = false;
                creatServer= false; 
                return;
            }

3.事件订阅

分别说明以下三个事件的功能。

//订阅数据到达事件,不能获取具体接收到的报文
//slave.DataStore.DataStoreWrittenTo += DataStoreWrittenToHandle;
//订阅接收到报文请求事件,可以打印接收到的报文
slave.ModbusSlaveRequestReceived += ModbusSlaveRequestReceivedHandle;
 //订阅接收到写入完成事件,可以打印写入完成响应
slave.WriteComplete += WriteCompleteHandle;

1.DataStore.DataStoreWrittenTo事件:当DataStore通过Modbus命令被写入数据时触发。

2.ModbusSlaveRequestReceived事件:当Slave收到主站报文时触发。

3.WriteComplete事件:当Slave接收到主站报文,并写入完成后触发。

本例主要使用后面【ModbusSlaveRequestReceived事件】和【WriteComplete事件】。

ModbusSlaveRequestReceived事件触发时,调用函数在提示框中打印报文信息,报文信息转换成16进制显示。

        private void ModbusSlaveRequestReceivedHandle(object obj, ModbusSlaveRequestEventArgs e)
        {
            string str = "";
            foreach (var item in e.Message.MessageFrame)
            {
                str += item.ToString("x2").PadLeft(2, '0').ToUpper() + "  ";    
            }
            WriteInfo("服务器收到报文:  " + str + "\r\n");
        }

WriteComplete事件,调用函数在提示框中打印报文信息,报文信息转换成16进制显示。

        private void WriteCompleteHandle(object sender, ModbusSlaveRequestEventArgs e)
        {
            string str = "";
            foreach (var item in e.Message.MessageFrame)
            {
                str += item.ToString("x2").PadLeft(2, '0').ToUpper() + "  ";
            }
            WriteInfo("服务器写入完成:  " + str + "\r\n");
        }

4.通讯示例

在服务器侧画面上,输入【IP】:127.0.0.1,【Port】:502,点击【创建服务器】,可观察到下方提示框中显示【创建服务器成功】。

打开Modbus Poll软件,在连接设置在远端服务器侧输入【IP地址】和【端口号】,点击确认连接。

连接成功后,PC端软件提示服务器收到报文,报文信息没有包含CRC字节信息;Modbus Poll端软件显示Tx=11,不断增加,这是由于默认使用了03功能读保持寄存器,数量长度为20个字,并循环读取。

Modbus Poll的配置如下: 

根据PC端软件已有功能,进行测试。

从站(服务器)写入,Modbus Poll(主站/客户端)读取:

【Value】输入2,点击【写1~10】,将向保持寄存器地址【1~10】写入值为Value*地址值,如:地址1=2;

地址2=4;

地址3=6;

地址4=8;

依次类推...如下图所示。

Modbus Poll(主站/客户端)写入,从站(服务器)读取:

Modbus Poll使用03功能码往保持寄存器地址11,写入123。 左侧软件提示框显示“服务器收到报文+收到报文”,此提示是由【ModbusSlaveRequestReceived事件】触发后发出;然后显示“服务器写入完成+收到报文”,此提示是由【WriteComplete事件】触发后发出。

Modbus Poll使用16功能码往保持寄存器地址11开始写10个寄存器,命令配置如下:

观察左侧软件提示框信息:

报文数据中的  00  0B  00  0C  00  0D  00  0E  00  0F  00  10  00  11  00  12  00  13  00  14

转换成10进制为11(00 0B),12(00 0C),13,14,15,16,17,18,19,20。

至此,基本通讯测试完成。

下面补充服务器端,如何对保持寄存器进行读写,其实很简单,就是直接访问slave.DataStore.HoldingRegisters[i]中的数据即可。

如下为写入代码:

            if (listener != null && slave!=null) {
                for (int i = 1;i<11;i++)
                {
                    slave.DataStore.HoldingRegisters[i] = (ushort)(numericUpDown2 .Value* i);
                }
                WriteInfo("服务器写入1~10完成" + "\r\n");
            }

以下为读取代码:

            if(slave!=null)
            {
                string str = "";
                for(int i=10;i<20;i++)
                {
                    str += slave.DataStore.HoldingRegisters[i+1].ToString() + "  ";
                }
                WriteInfo("读取寄存器(地址为10~20):"+str +"\r\n"); 
            }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1956797.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器视觉12-相机

相机 作用: 工业相机 是 机器视觉系统 的重要组成部分 最本质的功能就是通过CCD或CMOS成 像传感器将镜头产生的光信号转变为 有序的电信号&#xff0c;并将这些信息通过相 应接口传送到计算机主机 工业相机分类 目前业内没有对相机进行明确的分类定义&#xff0c; 以下分类是…

svn软件总成全内容

SVN软件总成 概述&#xff1a;本文为经验型文档 目录 D:\安装包\svn软件总成 的目录D:\安装包\svn软件总成\svn-base添加 的目录D:\安装包\svn软件总成\tools 的目录D:\安装包\svn软件总成\tools\sqlite-tools-win32-x86-3360000 的目录D:\安装包\svn软件总成\安装包-----bt lo…

一分钟搞定文件翻译|2024年4款翻译工具,职场达人都在用!

在全球化的大环境下&#xff0c;跨国沟通和协作变得非常普遍。不管是在公司间谈生意&#xff0c;还是跟外国朋友聊天&#xff0c;翻译文件成了我们经常要做的事情。但是一大堆文件和各种各样的语言&#xff0c;怎么才能又快又好地翻译出来&#xff0c;提升工作速度呢&#xff1…

本地部署Whisper Web结合内网穿透实现远程访问本地语音转文本模型

本地部署Whisper Web结合内网穿透实现远程访问本地语音转文本模型 &#x1f9d1; 博主简介&#xff1a;现任阿里巴巴嵌入式技术专家&#xff0c;15年工作经验&#xff0c;深耕嵌入式人工智能领域&#xff0c;精通嵌入式领域开发、技术管理、简历招聘面试。CSDN优质创作者&…

分享10个免费的职场办公常用工具网站

在现代职场中&#xff0c;高效办公工具网站的使用可以显著提升工作效率。小编今天就和大家分享10个免费实用且高质量的职场办公常用工具网站。 1.Convertio Convertio是一个万能文件转换工具&#xff0c;支持多种格式之间的转换&#xff0c;包括PDF、Excel、Word等。它操作简…

C#与欧姆龙PLC 通信——fins udp协议

前言 欧姆龙PLC在工控领域占有很大的市场份额,在上位机编程领域,实现上位机和欧姆龙PLC的通信也是必备的技能,上位机和PLC可以通过fins udp和fins tcp协议通信,本文介绍的是fins udp协议,该协议具有传输速度快的特点,为了帮助大家学习fins udp协议,我编写了“欧姆龙Fin…

【从0制作自己的ros导航小车:上、下位机通信篇】上、下位机串口DMA通信

从0制作自己的ros导航小车 前言一、准备工作二、下位机端&#xff08;STM32&#xff09;三、上位机端&#xff08;旭日x3派&#xff09;四、测试 前言 下位机的电机驱动、轮速读取、偏航角读取都已经完成&#xff0c;接下来就是上下位机的桥梁&#xff1a;串口通信。 使用USB转…

Mysql in 与 exists

在MySQL中&#xff0c;IN和EXISTS都是用于子查询的条件语句&#xff0c;但它们在性能和使用场景上有不同的特点和应用。下面是对它们的详细介绍以及示例说明&#xff1a;

springboot中小型酒店管理系统-计算机毕业设计源码02793

摘要 随着互联网和移动技术的快速发展&#xff0c;酒店行业也面临着巨大的变革和机遇。传统的酒店管理方式存在着信息不透明、预订流程繁琐等问题&#xff0c;无法满足现代消费者对便捷、高效、个性化服务的需求。因此&#xff0c;开发中小型酒店管理系统具有重要的意义。本文旨…

9000字干货:从消息流平台Serverless之路,看Serverless标准演进

本文分享自华为云社区《9000字干货&#xff1a;从消息流平台Serverless之路&#xff0c;看Serverless标准演进》 这是一个最美好的时代。 随着以数字化升级为代表的第四次工业革命浪潮的席卷&#xff0c;企业正在不断地深化运用这一技术&#xff0c;构建一个又一个全连接&…

module AttributeError: ‘matplotlib.cm has no attribute ‘register_cmap‘

使用seaborn或者matplotlib报错&#xff1a; module AttributeError: matplotlib.cm has no attribute register_cmap‘ 这个一般是matplotlib版本变化导致 register_cmap‘函数名称发生了改变&#xff0c;升高或者降低matplotlib版本版本即可。 实验后matplotlib 3.7.3 中不…

【漏洞复现】泛微E-Cology9 WorkPlanService 前台SQL注入

文章目录 0x00 漏洞描述影响范围 0x01 测绘工具0x02 漏洞复现0x03 Nuclei检测脚本0x04 修复建议0x05 免责声明 0x00 漏洞描述 泛微E-Cology9 是泛微网络科技股份有限公司开发的一款高效、灵活、全面的企业信息化办公系统。 泛微E-Cology9 中的 /services/WorkPlanService 接口…

docker一些常用的命令

查看当前正在运行的容器&#xff0c;使用docker ps命令&#xff0c;使用这个命令可以展示出容器列表&#xff0c;记住其中需要的容器id。 docker ps 使用docker exec命令进入容器。该命令的基本语法是&#xff1a;docker exec [选项] <容器名称或ID> <要执行的命令&…

Flink笔记整理(四)

Flink笔记整理&#xff08;四&#xff09; 文章目录 Flink笔记整理&#xff08;四&#xff09;六、Flink中的时间和窗口6.1 窗口&#xff08;Window&#xff09;窗口的概念窗口的分类窗口API概览窗口分配器窗口函数&#xff08;Window Functions&#xff09; 6.2 时间语义&…

LLama3 405B 技术解读

LLaMA 3 大模型效果提升的三要素 扩大模型和数据规模&#xff1a;通过Scaling Law增加模型参数数量和训练数据规模&#xff0c;以捕捉更复杂的模式。数据质量的重要性&#xff1a;确保高质量数据&#xff0c;通过筛选方法提升模型性能。理性能力数据的增加&#xff1a;在预训练…

Leetcode - 135双周赛

目录 一&#xff0c;3222. 求出硬币游戏的赢家 二&#xff0c;3223. 操作后字符串的最短长度 三&#xff0c;3224. 使差值相等的最少数组改动次数 四&#xff0c;3225. 网格图操作后的最大分数 一&#xff0c;3222. 求出硬币游戏的赢家 本题就是一道模拟题&#xff0c;每个…

vue自写组件可输入,可下拉选择,因为el-autocomplete数据多了会卡

<!-- 引入组件 --><AutoCompletev-model"scope.row.strreceivername":lngemployeeid"scope.row.lngreceiverid"select"handleSelect($event,scope.row)"/> methods:{handleSelect(item, row) {row.lngreceiverid item.lngemployeei…

NC 删除有序链表中重复的元素-II

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 描述 给出一个升序…

复杂系统科学之钥——从简单交互到宏观行为的涌现公式

复杂系统科学之钥——从简单交互到宏观行为的涌现公式 简单交互与宏观行为的类比 你可以把简单交互比作“音符”&#xff0c;而宏观行为就像是“乐章”&#xff0c;复杂系统科学就是研究如何从众多音符演奏出美妙乐章的学问。 复杂系统科学的核心作用 组件/步骤描述简单交互个…

这可能是开源界最好用的能源管理系统

&#x1f482; 个人网站: IT知识小屋&#x1f91f; 版权: 本文由【IT学习日记】原创、在CSDN首发、需要转载请联系博主&#x1f4ac; 如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连)和订阅专栏哦 文章目录 写在前面项目简介项目特点项目架构模块展示项目获取 写在前面 大…