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.hqwc.cn/news/99020.html

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

相关文章

k8s 启动和删除pod

k8s创建pod pod的启动流程 流程图 运维人员向kube-apiserver发出指令&#xff08;我想干什么&#xff0c;我期望事情是什么状态&#xff09; api响应命令,通过一系列认证授权,把pod数据存储到etcd,创建deployment资源并初始化。(期望状态&#xff09; controller通过list-wa…

MEMS传感器的原理与构造——单片式硅陀螺仪

一、前言 机械转子式陀螺仪在很长的一段时间内都是唯一的选项&#xff0c;也正是因为它的结构和原理&#xff0c;使其不再适用于现代小型、单体、集成式传感器的设计。常规的机械转子式陀螺仪包括平衡环、支撑轴承、电机和转子等部件&#xff0c;这些部件需要精密加工和…

博客程序系统其它功能扩充

一、注册功能 1、约定前后端接口 2、后端代码编写 WebServlet("/register") public class RegisterServlet extends HttpServlet {Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//设置…

哪个视觉语言模型更优?InstructBLIP、MiniGPT-4?全面评估基准LVLM-eHub告诉你

夕小瑶科技说 原创 作者 | 王思若 LLaMA、GPT-3等大型语言模型实现了对自然语言强大的理解和推理能力&#xff0c;为AI社区构筑了强大的语言基座模型。进而&#xff0c;继续迭代的GPT-4&#xff0c;更是赋予了模型处理图像的视觉能力。 如今&#xff0c;构建强大的多模态模型…

PMP是什么?项目管理专业人士资格认证介绍

PMP认证旨在评估和确认具备一定经验和知识的项目管理专业人士的能力。通过获得PMP认证&#xff0c;项目经理可以证明他们具备在各个行业中成功领导和管理项目所需的技能。这些技能包括十二原则、8大绩效等方面的知识。 以下是PMP认证的详细介绍&#xff1a; 1. 资格要求&…

java八股文面试[JVM]——引用计数、可达性分析

要想进行垃圾回收&#xff0c;得先知道什么样的对象是垃圾。 引用计数法 对于某个对象而言&#xff0c;只要应用程序中持有该对象的引用&#xff0c;就说明该对象不是垃圾&#xff0c;如果一个对象没有任何指针对其引用&#xff0c;它就是垃圾。 引用计数法在对象头处维护一…

LINUX内核启动流程-1

1、BIOS启动 硬件设置从OXFFFF0启动:CPU硬件设置加电即进入16位实模式状态运行,CPU硬件逻辑设计为加电瞬间强行将CS的值置为oxF000,IP的值置为0xFFF0,这样CS:IP就指向0xFFFF0这个地址位置。 BIOS程序的入口地址恰恰就是0xFFFF0 ! 也就是说,BIOS程序的第一条指令就设计在…

Linux执行命令

命令格式 主命令 选项 参数&#xff08;操作对象&#xff09;例如&#xff1a; 修改主机名 hostname set-hostname 新名称显示/目录下的文件的详细信息 ls -l /命令 内置命令&#xff08;builtin&#xff09;&#xff1a;shell程序自带的命令。 外部命令&#xff1a;有独立…

java+ssm+mysql水费管理系统

项目介绍&#xff1a; 使用javassmmysql开发的用户水费管理系统&#xff0c;系统包含超级管理员&#xff0c;系统管理员、用户角色&#xff0c;功能如下&#xff1a; 超级管理员&#xff1a;管理员管理、用户管理、用水管理&#xff08;用水记录、缴费提醒&#xff09;、水费…

prometheus通过blackbox-exporter监控web站点证书

1 概述 线上站点普遍是https&#xff0c;因此监控https web站点的证书的过期时间&#xff0c;是一个基础性需求。例如&#xff0c;证书过期会导致tls握手失败&#xff0c;进而导致用户无法正常访问web站点。 blackbox-expoter是一个web服务&#xff0c;它暴露了一个接口&#…

企业专题片的优势

企业专题片可以通过生动、感人的方式传达企业形象和信息&#xff0c;引起观众的共鸣和兴趣。它是一种强有力的营销工具&#xff0c;能够提升品牌形象、增加产品或服务的认知度&#xff0c;并在激烈的市场竞争中突显企业的实力和成果。企业专题片具有多个好处和影响&#xff0c;…

SpringBoot整合WebSocket

流程分析 Websocket客户端与Websocket服务器端 前端浏览器和后端服务器的连接通信 HTTP与Websocket对比 服务器端编码 1.引入pom依赖 <!--webSocket--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-sta…