C#通过ModbusTcp协议读写西门子PLC中的浮点数

一、Modbus TCP通信概述 

MODBUS/TCP是简单的、中立厂商的用于管理和控制自动化设备的MODBUS系列通讯协议的派生产品,显而易见,它覆盖了使用TCP/IP协议的“Intranet”和“Internet”环境中MODBUS报文的用途。协议的最通用用途是为诸如PLC,I/O模块,以及连接其它简单域总线或I/O模块的网关服务的。

Modbus TCP协议是在RTU协议前面添加MBAP报文头,由于TCP是基于可靠连接的服务,RTU协议中的CRC校验码就不再需要,所以在Modbus TCP协议中是没有CRC校验码。(使用上的主要区别)。MBAP报文头: 识( 2字节 ) 长度( 2字节 ) 单元标识符(1字节 )

目前Modbus TCP/IP协议主要应用领域Internet或Intranet中,而以太网传输距离远、传输速度快,使得应用范围广泛传输距离远、传输速度快,使得应用范围广泛。

 二. Modbus TCP使用的功能代码

modbus的操作对象有四种:线圈、离散输入、输入寄存器、保持寄存器

线圈:PLC的输出位,开关量,在MODBUS中可读可写
离散量:PLC的输入位,开关量,在MODBUS中只读
输入寄存器:PLC中只能从模拟量输入端改变的寄存器,在MODBUS中只读
保持寄存器:PLC中用于输出模拟量信号的寄存器,在MODBUS中可读可写
根据对象的不同,modbus的功能码有:

0x01:读线圈
0x02:读离散量输入
0x03:读保持寄存器

0x04:读输入寄存器

0x05:写单个线圈
0x06:写单个保持寄存器
0x10:写多个保持寄存器
0x0F:写多个线圈

 三、nmodbus4指南

 NModbus4是一个基于C#的Modbus协议库,可用于与Modbus RTU、ASCII、TCP和UDP设备进行通信。NModbus4中文版相当于对原版进行了翻译,使得不懂英文的人能够更方便地使用这个开源库进行编程。NModbus4是用C#编写的Modbus通信协议库,它支持的Modbus协议包括Modbus RTU、ASCII、TCP和UDP,可用于编程读写Modbus设备的寄存器和线圈。它完全符合Modbus协议规范,同时通过使用的事件调用机制,能够实现断线重连的功能。

NModbus4是一个完全开源的库,可以在GitHub上免费下载和使用

四、Modbus TCP通讯应用举例 

 4.1:搭建西门子博途V15的环境

搭建西门子仿真环境,需要先前掌握这些,看本人这些博客

windows10企业版安装西门子博途V15---01准备环境

windows10企业版安装西门子博途V15---02安装软件

windows10企业版安装西门子博途V15---03安装仿真软件

windows10企业版安装西门子博途V15---04连接测试
 

4.2:熟悉modbusTCP环境

需要先前掌握这些,看本人这些博客

4.3:创建PLC仿真环境

4.4: 博途V15创建项目

 本文最后会提供这个项目,只要打开即可

 4.5:创建数据块变量

4.6:创建tcp连接数据块

4.7:创建modbustcp通信模块

请注意,这里为什么是BYTE 20,是因为变量mf1到mf5共10寄存器,每个寄存器占2个字节,所以是20个字节,编译完成后,下载到Plc中

4.8:创建监控表

 

以上8个步骤就完成了modbustcp服务器,接下来搞程序,来读写Plc中的浮点数

4.9:创建winform项目

打开VS2019,创建窗体项目,布局很简单,4个button按钮

 

4.10:添加nmodbus4库

 

4.11:编写“nmodbus4读取一个float”代码

 /// <summary>/// nmodbus4读取一个float/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void button4_Click(object sender, EventArgs e){//nmodbus4读取到的数据都是ushort类型tcpClient = new TcpClient();tcpClient.Connect("192.168.1.199", 6800);//连接到主机master = ModbusIpMaster.CreateIp(tcpClient);//Ip 主站  byte slaveAddr = byte.Parse("1");//从站地址//ushort[] ReadHoldingRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints);表示读保持寄存器//slaveAddress从站地址(默认为1,通常也是1)//startAddress寄存器开始地址(这个地址是modbus的地址,不是Plc变量地址)//numberOfPoints寄存器数量(real类型占2个寄存器数量)ushort[] uDatas = master.ReadHoldingRegisters(slaveAddr, ushort.Parse("0"), ushort.Parse("2"));byte[] t = ByteArrayLib.GetByteArrayFromUShortArray(uDatas);//ushort数组转byte数组float[] floats = FloatLib.GetFloatArrayFromByteArray(t);//byte数组转float数组string fw1a = string.Join(",", floats);float fw1b = FloatLib.GetFloatFromByteArray(t, 0);//byte数组转floatMessageBox.Show("方式a:" + fw1a.ToString() + ",方式b:" + fw1b.ToString());uDatas = master.ReadHoldingRegisters(slaveAddr, ushort.Parse("2"), ushort.Parse("2"));t = ByteArrayLib.GetByteArrayFromUShortArray(uDatas);floats = FloatLib.GetFloatArrayFromByteArray(t);fw1a = string.Join(",", floats);fw1b = FloatLib.GetFloatFromByteArray(t, 0);MessageBox.Show("方式a:" + fw1a.ToString() + ",方式b:" + fw1b.ToString());uDatas = master.ReadHoldingRegisters(slaveAddr, ushort.Parse("4"), ushort.Parse("2"));t = ByteArrayLib.GetByteArrayFromUShortArray(uDatas);floats = FloatLib.GetFloatArrayFromByteArray(t);fw1a = string.Join(",", floats);fw1b = FloatLib.GetFloatFromByteArray(t, 0);MessageBox.Show("方式a:" + fw1a.ToString() + ",方式b:" + fw1b.ToString());uDatas = master.ReadHoldingRegisters(slaveAddr, ushort.Parse("6"), ushort.Parse("2"));t = ByteArrayLib.GetByteArrayFromUShortArray(uDatas);floats = FloatLib.GetFloatArrayFromByteArray(t);fw1a = string.Join(",", floats);fw1b = FloatLib.GetFloatFromByteArray(t, 0);MessageBox.Show("方式a:" + fw1a.ToString() + ",方式b:" + fw1b.ToString());uDatas = master.ReadHoldingRegisters(slaveAddr, ushort.Parse("8"), ushort.Parse("2"));t = ByteArrayLib.GetByteArrayFromUShortArray(uDatas);floats = FloatLib.GetFloatArrayFromByteArray(t);fw1a = string.Join(",", floats);fw1b = FloatLib.GetFloatFromByteArray(t, 0);MessageBox.Show("方式a:" + fw1a.ToString() + ",方式b:" + fw1b.ToString());master.Dispose();tcpClient.Dispose();}

运行效果

 全部读取到了PLC中的数据

 nmodbus4读取到的数据都是ushort类型

 ushort[] ReadHoldingRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints);表示读保持寄存器
            slaveAddress从站地址(默认为1,通常也是1)
            startAddress寄存器开始地址(这个地址是modbus的地址,不是Plc变量地址)
            numberOfPoints寄存器数量(real类型占2个寄存器数量)

 ushort[] uDatas = master.ReadHoldingRegisters(slaveAddr, ushort.Parse("0"), ushort.Parse("2"));

这个意思是读取从站地址1中的从0开始的2个寄存器数据,即%DB4.DBD0中的数据,结果是1.1

很多人搞不清楚,这个为何是开始地址0,数量是2,这就需要明白PLC中的地址与MODBUS地址的关系,另外nmodbus4读取到的数据都是ushort类型,因此需要进行类型转换,将ushort数组转byte数组,再将byte数组转float数组

4.12:编写“nmodbus4读取全部float”代码

 /// <summary>/// nmodbus4读取全部/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void button5_Click(object sender, EventArgs e){tcpClient = new TcpClient();tcpClient.Connect("192.168.1.188", 6800);//连接到主机master = ModbusIpMaster.CreateIp(tcpClient);//Ip 主站  byte slaveAddr = byte.Parse("1");ushort[] uDatas = master.ReadHoldingRegisters(slaveAddr, ushort.Parse("5"), ushort.Parse("10"));byte[] t = ByteArrayLib.GetByteArrayFromUShortArray(uDatas);float[] floats = FloatLib.GetFloatArrayFromByteArray(t);string fw1a = string.Join(",", floats);MessageBox.Show(fw1a.ToString());master.Dispose();tcpClient.Dispose();}

运行效果

4.13:编写“nmodbus4写入单个浮点”代码

/// <summary>/// nmodbus4写入单个浮点/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void button7_Click(object sender, EventArgs e){tcpClient = new TcpClient();tcpClient.Connect("192.168.1.199", 6800);//连接到主机master = ModbusIpMaster.CreateIp(tcpClient);//Ip 主站   //从站地址byte slaveAddr = byte.Parse("1");开始地址ushort startAddr = ushort.Parse("0");数据的值string vals = ("12.625");float[] uVals02 = vals.Split(',').Select(s => float.Parse(s)).ToArray();byte[] y = ByteArrayLib.GetByteArrayFromFloatArray(uVals02);ushort[] ushorts = UShortLib.GetUShortArrayFromByteArray(y);//void WriteMultipleRegisters(byte slaveAddress, ushort startAddress, ushort[] data);//写入多保持寄存器,意思是指向多个寄存器地址写入数据,也就是指同时向多个寄存器写入数据//slaveAddress表示从站地址,通常为1,默认也为1//startAddress表示寄存器开始地址,必须是ushort类型//data表示写入的具体数值,必须是ushort数组master.WriteMultipleRegisters(slaveAddr, startAddr, ushorts);//向第一个寄存器(地址是0)写入数据12.625MessageBox.Show("【 通过多保持寄存器】写入正数成功!");float floatValue = 12.625f;startAddr = ushort.Parse("2");byte[] byteArray = ByteArrayLib.GetByteArrayFromFloat(floatValue);//将字节数组中第0个开始的2个字节转换成ushort类型,即0,1ushort ua = UShortLib.GetUShortFromByteArray(byteArray, 0, DataFormat.ABCD);master.WriteSingleRegister(slaveAddr, startAddr, ua);//向从站地址1中的第3个寄存器(地址为2)写入数据ua//将字节数组中第2个开始的2个字节转换成ushort类型,即2,3 ushort ub = UShortLib.GetUShortFromByteArray(byteArray, 2, DataFormat.ABCD);startAddr = ushort.Parse("3");master.WriteSingleRegister(slaveAddr, startAddr, ub);//向从站地址1中的第4个寄存器(地址为3)写入数据ubMessageBox.Show("【 通过单保持寄存器】写入正数成功!"); vals = ("-18.326");startAddr = ushort.Parse("8");uVals02 = vals.Split(',').Select(s => float.Parse(s)).ToArray();y = ByteArrayLib.GetByteArrayFromFloatArray(uVals02);ushorts = UShortLib.GetUShortArrayFromByteArray(y);master.WriteMultipleRegisters(slaveAddr, startAddr, ushorts);MessageBox.Show("【 通过多保持寄存器】写入负数成功!");master.Dispose();tcpClient.Dispose();}

 运行效果

 4.14:编写“nmodbus4写入多个浮点"代码

 /// <summary>/// nmodbus4写入多个浮点/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void button6_Click(object sender, EventArgs e){tcpClient = new TcpClient();tcpClient.Connect("192.168.1.199", 6800);//连接到主机master = ModbusIpMaster.CreateIp(tcpClient);//Ip 主站  //从站地址byte slaveAddr = byte.Parse("1");//开始地址ushort startAddr = ushort.Parse("0");//数据的值string vals = ("4.9635,6.9635,-1.28,67,-902");float[] uVals02 = vals.Split(',').Select(s => float.Parse(s)).ToArray();byte[] y = ByteArrayLib.GetByteArrayFromFloatArray(uVals02);ushort[] ushorts = UShortLib.GetUShortArrayFromByteArray(y);master.WriteMultipleRegisters(slaveAddr, startAddr, ushorts);MessageBox.Show("【 多保持寄存器】写入成功!");master.Dispose();tcpClient.Dispose();}

 运行效果

浮点数包括整数,小数,也包括正数或负数,所以正整数,负整数,正小数,负小数都可以写入

五:modbustcp协议小结

MODBUS TCP 结合了以太网物理网络和网络标准 TCP/IP 以及以 MODBUS 作为应用协议标准的数据表示方法。MODBUS TCP 通信报文被封装于以太网 TCP/IP 数据包中,MODBUS 协议规范一帧数据的最大长度为 256 个字节。

MODBUS TCP/IP 的通信系统中有两种类型的设备:MODBUS TCP/IP 客户端和服务器设备。

1.MODBUS 客户端

客户端(TCP Client)主动向服务器(TCP Server)发起连接请求,连接建立成功,仅允许客户端主动发起通讯请求。

以太网机型作为 MODBUS TCP 客户端时,通过 S_OPEN 指令建立 TCP 连接,通过 M_TCP 指令发起 MODBUS 请求。

2.MODBUS 服务器

服务器主动监听 502 端口,等待客户端连接请求,连接建立成功,响应符合 Modbus TCP 协议规范的数据通讯请求。

3.优势 

优势: 免费、简单、容易使用,Modbus协议是现在国内工业领域应用最多的协议,不只PLC设备,各种终端设备,比如水控机、水表、电表、工业秤、各种采集设备,

4.特点

  1. 采用主从问答方式进行通信

  2. Modbus TCP是应用层协议,基于传输层TCP协议实现

  3. Modbus TCP端口号默认为502,但在本案例中修改成6800,当然你也可以改成别的

六:代码下载

 链接:https://pan.baidu.com/s/1mARLDATOBphLKbecj4sW8g 
提取码:lggv  

 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LiveGBS流媒体平台GB/T28181功能-支持数据库切换为高斯数据库信创瀚高数据信创数据库

LiveGBS流媒体平台GB/T28181功能-支持数据库切换为高斯数据库信创瀚高数据信创数据库 1、如何配置切换高斯数据库&#xff1f;2、如何配置切换信创瀚高数据库&#xff1f;3、搭建GB28181视频直播平台 1、如何配置切换高斯数据库&#xff1f; livecms.ini -> [db]下面添加配…

华为Mate60低调发布,你所不知道的高调真相?

华为Mate60 pro 这两天的劲爆新闻想必各位早已知晓&#xff0c;那就是华为Mate60真的来了&#xff01;&#xff01;&#xff01;并且此款手机搭载了最新国产麒麟9000s芯片&#xff0c;该芯片重新定义了手机性能的巅峰。不仅在Geekbench测试中表现出色&#xff0c;还在实际应用…

成都瀚网科技有限公司:抖店的评论会消失吗?

抖店是抖音推出的电子商务平台。很多用户在购物后都会对产品进行评价。但有时用户可能会发现抖店评论缺失&#xff0c;让用户产生一些疑惑和困惑。本文将围绕这个问题提供一些答案和解决方案。 1.为什么抖店评论不见了&#xff1f; 首先需要明确的是&#xff0c;抖店评论消失可…

单值二叉树

目录 题目题目要求示例 解答方法一、实现思路时间复杂度和空间复杂度代码 方法二、实现思路时间复杂度和空间复杂度代码 题目 单值二叉树 题目要求 题目链接 示例 解答 方法一、 递归 实现思路 时间复杂度和空间复杂度 时间复杂度&#xff1a;O(N) 空间复杂度&#xf…

Jenkins详解(三)

Jenkins详解(三) 目录 Jenkins详解(三) 1、Jenkins介绍2、Jenkins CI/CD 流程3、部署环境 3.1 环境准备3.2 安装GitLab3.3 初始化GitLab3.4 GitLab中文社区版补丁包安装3.5 修改GitLab配置文件/etc/gitlab/gitlab.rb3.6 在宿主机输入 http://192.168.200.26:88 地址就可以访问了…

什么是AJAX?如何使用原生JavaScript搭建AJAX请求?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ AJAX&#xff08;Asynchronous JavaScript and XML&#xff09;⭐ 原生JavaScript中的AJAX请求1. 创建XMLHttpRequest对象2. 配置请求3. 设置回调函数4. 发送请求 ⭐ 完整示例⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开…

实现Android APK瘦身99.99%

摘要&#xff1a; 如何瘦身是 APK 的重要优化技术。APK 在安装和更新时都需要经过网络下载到设备&#xff0c;APK 越小&#xff0c;用户体验越好。本文作者通过对 APK 内在机制的详细解析&#xff0c;给出了对 APK 各组成成分的优化方法及技术&#xff0c;并实现了一个基本 APK…

Unity 安卓(Android)端AVProVideo插件播放不了视频,屏幕一闪一闪的

编辑器运行没有问题&#xff0c;但是安卓就有问题&#xff0c;在平板上运行就会报错&#xff1a; vulkan graphics API is notsupported 说不支持Vulkan图形API,解决方法&#xff1a;把Vulkan删除掉

QTableView合并单元格

QtableView的功能 QTableView是Qt框架提供的用于显示表格数据的类。它是基于MVC&#xff08;模型-视图-控制器&#xff09;设计模式的一部分&#xff0c;用于将数据模型和界面视图分离。 以下是一些QTableView的主要特点和功能&#xff1a; 1. 显示表格数据&#xff1a; QTa…

手写Mybatis:第20章-Mybatis 框架源码10种设计模式分析

文章目录 一、类型&#xff1a;创建型模式1.1 工厂模式1.2 单例模式1.3 建造者模式 二、类型&#xff1a;结构型模式2.1 适配器模式2.2 代理模式2.3 组合模式2.4 装饰器模式 三、类型&#xff1a;行为型模式3.1 模板模式3.2 策略模式3.3 迭代器模式 一、类型&#xff1a;创建型…

题①拷贝构造相关笔试题

问&#xff1a;此代码中有几次构造&#xff0c;几次拷贝构造&#xff1f; W f&#xff08;W u&#xff09; {W v(u);W w v;return w; } int main() {w x;w y f(x);return 0;解析&#xff1a;一次构造&#xff0c;四次拷贝构造。 再来一题 W f&#xff08;W u&#xff09;…

Redis未授权访问漏洞复现

Redis 简单使用 Redis 未设置密码&#xff0c;客户端工具可以直接链接。 Redis 是非关系型数据库系统&#xff0c;没有库表列的逻辑结构&#xff0c;仅仅以键值对的方式存储数据。 先启动容器 Redis 未设置密码&#xff0c;客户端工具可以直接链接 https://github.com/xk11z/…

Laravel 模型的关联查询 Debugbar 调试器 模型的预加载 ⑩②

作者 : SYFStrive 博客首页 : HomePage &#x1f4dc;&#xff1a; THINK PHP &#x1f4cc;&#xff1a;个人社区&#xff08;欢迎大佬们加入&#xff09; &#x1f449;&#xff1a;社区链接&#x1f517; &#x1f4cc;&#xff1a;觉得文章不错可以点点关注 &#x1f44…

冠达管理:券商8月调研热情高 工业机械行业受青睐

截至9月4日记者发稿&#xff0c;8月以来券商累计调研次数约1.44万次&#xff0c;环比增加超160%。其间&#xff0c;工业机械职业公司获券商调研最多。 调研逾900只个股 截至9月4日发稿&#xff0c;8月以来券商累计调研948只个股。从个股调研热度看&#xff0c;容百科技最受券…

【ES6】JavaScript中的Symbol

Symbol是JavaScript中的一种特殊的、不可变的、不可枚举的数据类型。它通常用于表示一个唯一的标识符&#xff0c;可以作为对象的属性键&#xff0c;确保对象的属性键的唯一性和不可变性。 Symbol.for()是Symbol的一个方法&#xff0c;它用于创建一个已经注册的Symbol对象。当…

基于Matlab实现多个图像融合案例(附上源码+数据集)

图像融合是将多幅图像合成为一幅图像的过程&#xff0c;旨在融合不同图像的信息以获得更多的细节和更丰富的视觉效果。在本文中&#xff0c;我们将介绍如何使用Matlab实现图像融合。 文章目录 简单案例源码数据集下载 简单案例 首先&#xff0c;我们需要了解图像融合的两种主…

理解 std::thread::join

C多线程并发编程入门&#xff08;目录&#xff09; 本文用最简单易懂的实际案例&#xff0c;讲清楚了 join 的实际内涵&#xff0c;保证你过目不忘。 Hello join 示例 join 函数是我们接触C多线程 thread 遇到的第一个函数。 比如&#xff1a; int main() {thread t(f);t.…

修改PX4飞控的imu频率

QGroundControl 连接上飞控后&#xff0c;打开 Analyze Tools 下的 MAVLink Inspector 界面 可以看到当前的 IMU 频率为50 HZ&#xff0c;或者在终端启动 mavros&#xff0c;终端输入 sudo chmod 777 /dev/ttyACM0 roslaunch mavros px4.launch 然后查看频率 rostopic hz /m…

大数据平台三大优势详解-行云管家

大数据平台三大优势详解 1、轻松进行数据共享 企业在管理以及快速发展过程中&#xff0c;有着越来越多的数据需要进行管理&#xff0c;如果单独管理则工作量巨大&#xff0c;且难免出现问题&#xff0c;同时共享难。因此需要大数据平台对数据进行统一管理&#xff0c;以及轻松…

科技驱动产业升级:浅谈制造型企业对MES系统的应用

在科技不断进步的背景下&#xff0c;制造型行业也在持续发展&#xff0c;但随之而来的挑战也不断增加。传统的管理方式已经无法满足企业的需求&#xff0c;因此许多制造型企业开始寻找新的管理模式。制造执行系统&#xff08;MES&#xff09;作为先进的制造信息技术之一&#x…