Modbus Rtu的实现与Modbus Tcp的实现类似
C#ModBus Tcp的学习及Master的实现
我们还是需要借用一个开源库NModbus4,在vs中.打开NuGet管理器.安装NModbus4
具体实现,具体实现与之前的Modbus Tcp的实现类似 ,只是在实例化master时将TCPClient换为串行端口资源SerialPort,并在实例化时设置好端口所需参数(端口名,波特率,校验位,停止位,数据位)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Modbus.Device;
using System.Net.Sockets;
using System.Threading;
using System.IO.Ports;
namespace ModbusRtu
public partial class Form1 : Form
private static IModbusMaster master;
private static SerialPort port;
//写线圈或写寄存器数组
private bool[] coilsBuffer;
private ushort[] registerBuffer;
//功能码
private string functionCode;
//参数(分别为站号,起始地址,长度)
private byte slaveAddress;
private ushort startAddress;
private ushort numberOfPoints;
//串口参数
private string portName;
private int baudRate;
private Parity parity;
private int dataBits;
private StopBits stopBits;
public Form1()
InitializeComponent();
private void Form1_Load(object sender, EventArgs e)
cmb_portname.SelectedIndex = 0;
cmb_baud.SelectedIndex = 5;
cmb_parity.SelectedIndex = 2;
cmb_databBits.SelectedIndex = 1;
cmb_stopBits.SelectedIndex = 0;
private SerialPort InitSerialPortParameter()
if (cmb_portname.SelectedIndex < 0 || cmb_baud.SelectedIndex < 0 || cmb_parity.SelectedIndex < 0 || cmb_databBits.SelectedIndex < 0 || cmb_stopBits.SelectedIndex < 0)
MessageBox.Show("请选择串口参数");
return null;
portName = cmb_portname.SelectedItem.ToString();
baudRate = int.Parse(cmb_baud.SelectedItem.ToString());
switch (cmb_parity.SelectedItem.ToString())
case "奇":
parity = Parity.Odd;
break;
case "偶":
parity = Parity.Even;
break;
case "无":
parity = Parity.None;
break;
default:
break;
dataBits = int.Parse(cmb_databBits.SelectedItem.ToString());
switch (cmb_stopBits.SelectedItem.ToString())
case "1":
stopBits = StopBits.One;
break;
case "2":
stopBits = StopBits.Two;
break;
default:
break;
port = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
return port;
/// <summary>
/// 读/写
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
//初始化串口参数
InitSerialPortParameter();
master = ModbusSerialMaster.CreateRtu(port);
ExecuteFunction();
catch (Exception)
MessageBox.Show("初始化异常");
private async void ExecuteFunction()
//每次操作是要开启串口 操作完成后需要关闭串口
//目的是为了slave更换连接是不报错
if (port.IsOpen == false)
port.Open();
if (functionCode != null)
switch (functionCode)
case "01 Read Coils"://读取单个线圈
SetReadParameters();
coilsBuffer = master.ReadCoils(slaveAddress, startAddress, numberOfPoints);
for (int i = 0; i < coilsBuffer.Length; i++)
SetMsg(coilsBuffer[i] + " ");
SetMsg("\r\n");
break;
case "02 Read DisCrete Inputs"://读取输入线圈/离散量线圈
SetReadParameters();
coilsBuffer = master.ReadInputs(slaveAddress, startAddress, numberOfPoints);
for (int i = 0; i < coilsBuffer.Length; i++)
SetMsg(coilsBuffer[i] + " ");
SetMsg("\r\n");
break;
case "03 Read Holding Registers"://读取保持寄存器
SetReadParameters();
registerBuffer = master.ReadHoldingRegisters(slaveAddress, startAddress, numberOfPoints);
for (int i = 0; i < registerBuffer.Length; i++)
SetMsg(registerBuffer[i] + " ");
SetMsg("\r\n");
break;
case "04 Read Input Registers"://读取输入寄存器
SetReadParameters();
registerBuffer = master.ReadInputRegisters(slaveAddress, startAddress, numberOfPoints);
for (int i = 0; i < registerBuffer.Length; i++)
SetMsg(registerBuffer[i] + " ");
SetMsg("\r\n");
break;
case "05 Write Single Coil"://写单个线圈
SetWriteParametes();
await master.WriteSingleCoilAsync(slaveAddress, startAddress, coilsBuffer[0]);
break;
case "06 Write Single Registers"://写单个输入线圈/离散量线圈
SetWriteParametes();
await master.WriteSingleRegisterAsync(slaveAddress, startAddress, registerBuffer[0]);
break;
case "0F Write Multiple Coils"://写一组线圈
SetWriteParametes();
await master.WriteMultipleCoilsAsync(slaveAddress, startAddress, coilsBuffer);
break;
case "10 Write Multiple Registers"://写一组保持寄存器
SetWriteParametes();
await master.WriteMultipleRegistersAsync(slaveAddress, startAddress, registerBuffer);
break;
default:
break;
MessageBox.Show("请选择功能码!");
port.Close();
catch (Exception ex)
MessageBox.Show(ex.Message);
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
if (comboBox1.SelectedIndex >= 4)
groupBox2.Enabled = true;
groupBox1.Enabled = false;
groupBox1.Enabled = true;
groupBox2.Enabled = false;
comboBox1.Invoke(new Action(() => { functionCode = comboBox1.SelectedItem.ToString(); }));
/// <summary>
/// 初始化读参数
/// </summary>
private void SetReadParameters()
if (txt_startAddr1.Text == "" || txt_slave1.Text == "" || txt_length.Text == "")
MessageBox.Show("请填写读参数!");
slaveAddress = byte.Parse(txt_slave1.Text);
startAddress = ushort.Parse(txt_startAddr1.Text);
numberOfPoints = ushort.Parse(txt_length.Text);
/// <summary>
/// 初始化写参数
/// </summary>
private void SetWriteParametes()
if (txt_startAddr2.Text == "" || txt_slave2.Text == "" || txt_data.Text == "")
MessageBox.Show("请填写写参数!");
slaveAddress = byte.Parse(txt_slave2.Text);
startAddress = ushort.Parse(txt_startAddr2.Text);
//判断是否写线圈
if (comboBox1.SelectedIndex == 4 || comboBox1.SelectedIndex == 6)
string[] strarr = txt_data.Text.Split(' ');
coilsBuffer = new bool[strarr.Length];
//转化为bool数组
for (int i = 0; i < strarr.Length; i++)
// strarr[i] == "0" ? coilsBuffer[i] = true : coilsBuffer[i] = false;
if (strarr[i] == "0")
coilsBuffer[i] = false;
coilsBuffer[i] = true;
//转化ushort数组
string[] strarr = txt_data.Text.Split(' ');
registerBuffer = new ushort[strarr.Length];
for (int i = 0; i < strarr.Length; i++)
registerBuffer[i] = ushort.Parse(strarr[i]);
/// <summary>
/// 清除文本
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
richTextBox1.Clear();
/// <summary>
/// SetMessage
/// </summary>
/// <param name="msg"></param>
public void SetMsg(string msg)
richTextBox1.Invoke(new Action(() => { richTextBox1.AppendText(msg); }));
接下来开始测试
在这里 因为要用到串口,而我的笔记本没有串口,所以需要借助一个工具
Virtual Serial Port Dirver 虚拟串口工具
链接:https://pan.baidu.com/s/1opGre3GS-HWFoA_dP9qYYg
提取码:2afu
借用这个工具我们添加两个虚拟串口 COM1和COM2 点击Add Virtual Pair 添加
设置Modbus Slave,选择连接方式为串口,选择对应端口,模式选择RTU,建立连接
接下来运行我们自己的Modbus RTU Master
设置串口参数(波特率,数据位,奇偶校验,停止位)要与Slave的串口参数一致
我们测试 功能码 0x01 读一组线圈
测试完成,数据正常,其他的功能码经测试数据正常,有兴趣的可以自行测试
到此为止,Modbus的学习到此告一段落
以上都为我自行学习并实现,如有错误之处,望大家不吝赐教,感谢(抱拳~)
程序源代码:
链接:https://pan.baidu.com/s/1mPAhRixLbsDb7h2ePENTRA
提取码:b5w6
作者: Peter.Pan
出处: https://www.cnblogs.com/pandefu/>
邮箱: defu_pan@163.com
关于作者:.Net,WindowsForm,工控软件,Modbus,OPC/Tcp/Ip,串口通讯
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出 原文链接,否则保留追究法律责任的权利。 如有问题, 可邮件咨询。
https://www.cnblogs.com/pandefu/p/10849823.html
Modbus Rtu的实现与Modbus Tcp的实现类似 C#ModBus Tcp的学习及Master的实现我们还是需要借用一个开源库NModbus4,在vs中.打开NuGet管理器.安装NModbus4具体实现,具体实现与之前的Modbus Tcp的实现类似 ,只是在实例化master时将TCPClient换为串行端口资源SerialPort,并在实例化时设置好端口所需参数(端口名,波特率,校验位,停止位,数据位)using System;using System.Collectio
Modbus已经成为工业领域通信协议的业界标准(De facto),并且现在是工业电子设备之间常用的连接方式。所以这也是我们工控领域软件开发的所必懂的通讯协议,我也是初次学习,先贴上我的学习笔记.
一 、协议概述
1、Modbus协议是应用于控制器上的一种通用语言,实现控制器之间,控制器通过网络和其他设备之间的通信,支持传统RS232/RS422/RS485和以太网设备,它已经成为一种通用的工业标准,有了它不同厂商生产的控制设备可以连成工业网络,进行集中控制,此协议定义了一个控制器能认识...
Modbus是一种串行通信协议,是Modicon公司(现在的施耐德电气Schneider Electric)于1979年为使用可编程逻辑控制器(PLC)通信而发表。Modbus已经成为工业领域通信协议的业界标准(De facto),并且现在是工业电子设备之间常用的连接方式。[1]Modbus比其他通信协议使用的更广泛的主要原因有:[2]
公开发表并且无版权要求...
C#Modbus Rtu的实现
在次记录一下自己的学习资料,只为对网上的数据收集,方便以后查找,如若侵犯版权请联系删除
Modbus Rtu的实现与Modbus Tcp的实现类似https://www.cnblogs.com/pandefu/p/10824331.html
我们还是需要借用一个开源库NModbus4,在vs中.打开NuGet管理器.安装NModbus4
具体实现,具体实现与之前的Modbus Tcp的实现类似 ,只是在实例化master时将TCPClient换为串行端口资源SerialPo
C# Modbus RTU 是一个用于在 C# 编程语言中实现 Modbus RTU 通信协议的库或组件。Modbus RTU 是一种常用的串行通信协议,用于在工业自动化领域中连接和通信设备。通过使用 C# Modbus RTU 库,您可以轻松地在 C# 应用程序中实现与 Modbus RTU 设备的通信。
您可以使用 C# Modbus RTU 库来读取和写入 Modbus RTU 设备的寄存器、线圈和其他数据。该库提供了一组函数和类,以简化与 Modbus RTU 设备之间的通信过程。您可以使用这些函数和类来建立与设备的连接、发送请求、接收响应以及解析数据。
为了使用 C# Modbus RTU 库,您需要先安装该库,并且了解基本的 Modbus RTU 通信协议。然后,您可以在您的 C# 项目中引用该库,并使用提供的类和方法来实现与 Modbus RTU 设备的通信。
请注意,C# Modbus RTU 库可能由不同的开发者开发和维护,因此具体的用法和 API 可能会有所不同。建议您查阅相关文档或示例代码以获取更详细的信息和使用说明。