C#简易Modbus从站仿真器

news2025/5/13 17:31:30

       C#使用NModbus库,编写从站仿真器,支持Modbus TCP访问,支持多个从站地址和动态启用/停用从站(模拟离线),支持数据变化,可以很方便实现,最终效果如图所示。

项目采用.net framework 4.7的Windows窗体模式快速实现,NuGet包和版本如下:

界面设计如下:

窗体设计部分Form1.Designer.cs代码如下:

namespace ModbusSlaveSimulatorTest
{
    partial class Form1
    {
        /// <summary>
        /// 必需的设计器变量。
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows 窗体设计器生成的代码

        /// <summary>
        /// 设计器支持所需的方法 - 不要修改
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.checkBox1 = new System.Windows.Forms.CheckBox();
            this.checkBox2 = new System.Windows.Forms.CheckBox();
            this.checkBox3 = new System.Windows.Forms.CheckBox();
            this.checkBox4 = new System.Windows.Forms.CheckBox();
            this.checkBox5 = new System.Windows.Forms.CheckBox();
            this.checkBox6 = new System.Windows.Forms.CheckBox();
            this.checkBox7 = new System.Windows.Forms.CheckBox();
            this.checkBox8 = new System.Windows.Forms.CheckBox();
            this.checkBox9 = new System.Windows.Forms.CheckBox();
            this.checkBox10 = new System.Windows.Forms.CheckBox();
            this.timer1 = new System.Windows.Forms.Timer(this.components);
            this.label1 = new System.Windows.Forms.Label();
            this.comboBox1 = new System.Windows.Forms.ComboBox();
            this.SuspendLayout();
            // 
            // checkBox1
            // 
            this.checkBox1.AutoSize = true;
            this.checkBox1.Checked = true;
            this.checkBox1.CheckState = System.Windows.Forms.CheckState.Checked;
            this.checkBox1.Location = new System.Drawing.Point(12, 12);
            this.checkBox1.Name = "checkBox1";
            this.checkBox1.Size = new System.Drawing.Size(66, 16);
            this.checkBox1.TabIndex = 0;
            this.checkBox1.Text = "Slave 1";
            this.checkBox1.UseVisualStyleBackColor = true;
            this.checkBox1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.checkBox9_MouseClick);
            // 
            // checkBox2
            // 
            this.checkBox2.AutoSize = true;
            this.checkBox2.Checked = true;
            this.checkBox2.CheckState = System.Windows.Forms.CheckState.Checked;
            this.checkBox2.Location = new System.Drawing.Point(84, 12);
            this.checkBox2.Name = "checkBox2";
            this.checkBox2.Size = new System.Drawing.Size(66, 16);
            this.checkBox2.TabIndex = 1;
            this.checkBox2.Text = "Slave 2";
            this.checkBox2.UseVisualStyleBackColor = true;
            this.checkBox2.MouseClick += new System.Windows.Forms.MouseEventHandler(this.checkBox9_MouseClick);
            // 
            // checkBox3
            // 
            this.checkBox3.AutoSize = true;
            this.checkBox3.Checked = true;
            this.checkBox3.CheckState = System.Windows.Forms.CheckState.Checked;
            this.checkBox3.Location = new System.Drawing.Point(167, 12);
            this.checkBox3.Name = "checkBox3";
            this.checkBox3.Size = new System.Drawing.Size(66, 16);
            this.checkBox3.TabIndex = 2;
            this.checkBox3.Text = "Slave 3";
            this.checkBox3.UseVisualStyleBackColor = true;
            this.checkBox3.MouseClick += new System.Windows.Forms.MouseEventHandler(this.checkBox9_MouseClick);
            // 
            // checkBox4
            // 
            this.checkBox4.AutoSize = true;
            this.checkBox4.Checked = true;
            this.checkBox4.CheckState = System.Windows.Forms.CheckState.Checked;
            this.checkBox4.Location = new System.Drawing.Point(251, 12);
            this.checkBox4.Name = "checkBox4";
            this.checkBox4.Size = new System.Drawing.Size(66, 16);
            this.checkBox4.TabIndex = 3;
            this.checkBox4.Text = "Slave 4";
            this.checkBox4.UseVisualStyleBackColor = true;
            this.checkBox4.MouseClick += new System.Windows.Forms.MouseEventHandler(this.checkBox9_MouseClick);
            // 
            // checkBox5
            // 
            this.checkBox5.AutoSize = true;
            this.checkBox5.Checked = true;
            this.checkBox5.CheckState = System.Windows.Forms.CheckState.Checked;
            this.checkBox5.Location = new System.Drawing.Point(342, 12);
            this.checkBox5.Name = "checkBox5";
            this.checkBox5.Size = new System.Drawing.Size(66, 16);
            this.checkBox5.TabIndex = 4;
            this.checkBox5.Text = "Slave 5";
            this.checkBox5.UseVisualStyleBackColor = true;
            this.checkBox5.MouseClick += new System.Windows.Forms.MouseEventHandler(this.checkBox9_MouseClick);
            // 
            // checkBox6
            // 
            this.checkBox6.AutoSize = true;
            this.checkBox6.Checked = true;
            this.checkBox6.CheckState = System.Windows.Forms.CheckState.Checked;
            this.checkBox6.Location = new System.Drawing.Point(432, 12);
            this.checkBox6.Name = "checkBox6";
            this.checkBox6.Size = new System.Drawing.Size(66, 16);
            this.checkBox6.TabIndex = 5;
            this.checkBox6.Text = "Slave 6";
            this.checkBox6.UseVisualStyleBackColor = true;
            this.checkBox6.MouseClick += new System.Windows.Forms.MouseEventHandler(this.checkBox9_MouseClick);
            // 
            // checkBox7
            // 
            this.checkBox7.AutoSize = true;
            this.checkBox7.Checked = true;
            this.checkBox7.CheckState = System.Windows.Forms.CheckState.Checked;
            this.checkBox7.Location = new System.Drawing.Point(516, 12);
            this.checkBox7.Name = "checkBox7";
            this.checkBox7.Size = new System.Drawing.Size(66, 16);
            this.checkBox7.TabIndex = 6;
            this.checkBox7.Text = "Slave 7";
            this.checkBox7.UseVisualStyleBackColor = true;
            this.checkBox7.MouseClick += new System.Windows.Forms.MouseEventHandler(this.checkBox9_MouseClick);
            // 
            // checkBox8
            // 
            this.checkBox8.AutoSize = true;
            this.checkBox8.Checked = true;
            this.checkBox8.CheckState = System.Windows.Forms.CheckState.Checked;
            this.checkBox8.Location = new System.Drawing.Point(588, 12);
            this.checkBox8.Name = "checkBox8";
            this.checkBox8.Size = new System.Drawing.Size(66, 16);
            this.checkBox8.TabIndex = 7;
            this.checkBox8.Text = "Slave 8";
            this.checkBox8.UseVisualStyleBackColor = true;
            this.checkBox8.MouseClick += new System.Windows.Forms.MouseEventHandler(this.checkBox9_MouseClick);
            // 
            // checkBox9
            // 
            this.checkBox9.AutoSize = true;
            this.checkBox9.Checked = true;
            this.checkBox9.CheckState = System.Windows.Forms.CheckState.Checked;
            this.checkBox9.Location = new System.Drawing.Point(660, 12);
            this.checkBox9.Name = "checkBox9";
            this.checkBox9.Size = new System.Drawing.Size(66, 16);
            this.checkBox9.TabIndex = 8;
            this.checkBox9.Text = "Slave 9";
            this.checkBox9.UseVisualStyleBackColor = true;
            this.checkBox9.MouseClick += new System.Windows.Forms.MouseEventHandler(this.checkBox9_MouseClick);
            // 
            // checkBox10
            // 
            this.checkBox10.AutoSize = true;
            this.checkBox10.Checked = true;
            this.checkBox10.CheckState = System.Windows.Forms.CheckState.Checked;
            this.checkBox10.Location = new System.Drawing.Point(12, 57);
            this.checkBox10.Name = "checkBox10";
            this.checkBox10.Size = new System.Drawing.Size(96, 16);
            this.checkBox10.TabIndex = 9;
            this.checkBox10.Text = "数据随机变化";
            this.checkBox10.UseVisualStyleBackColor = true;
            this.checkBox10.CheckedChanged += new System.EventHandler(this.checkBox10_CheckedChanged);
            // 
            // timer1
            // 
            this.timer1.Enabled = true;
            this.timer1.Interval = 2000;
            this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(148, 58);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(101, 12);
            this.label1.TabIndex = 10;
            this.label1.Text = "仿真频率(ms):";
            // 
            // comboBox1
            // 
            this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            this.comboBox1.FormattingEnabled = true;
            this.comboBox1.Items.AddRange(new object[] {
            "100",
            "200",
            "500",
            "1000",
            "2000",
            "5000",
            "10000"});
            this.comboBox1.Location = new System.Drawing.Point(247, 56);
            this.comboBox1.Name = "comboBox1";
            this.comboBox1.Size = new System.Drawing.Size(70, 20);
            this.comboBox1.TabIndex = 11;
            this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(802, 125);
            this.Controls.Add(this.comboBox1);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.checkBox10);
            this.Controls.Add(this.checkBox9);
            this.Controls.Add(this.checkBox8);
            this.Controls.Add(this.checkBox7);
            this.Controls.Add(this.checkBox6);
            this.Controls.Add(this.checkBox5);
            this.Controls.Add(this.checkBox4);
            this.Controls.Add(this.checkBox3);
            this.Controls.Add(this.checkBox2);
            this.Controls.Add(this.checkBox1);
            this.Name = "Form1";
            this.Text = "Modbus从站仿真";
            this.Load += new System.EventHandler(this.Form1_Load);
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.CheckBox checkBox1;
        private System.Windows.Forms.CheckBox checkBox2;
        private System.Windows.Forms.CheckBox checkBox3;
        private System.Windows.Forms.CheckBox checkBox4;
        private System.Windows.Forms.CheckBox checkBox5;
        private System.Windows.Forms.CheckBox checkBox6;
        private System.Windows.Forms.CheckBox checkBox7;
        private System.Windows.Forms.CheckBox checkBox8;
        private System.Windows.Forms.CheckBox checkBox9;
        private System.Windows.Forms.CheckBox checkBox10;
        private System.Windows.Forms.Timer timer1;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.ComboBox comboBox1;
    }
}

窗体实现部分代码如下:

using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Net;
using System.Windows.Forms;
using NModbus;

namespace ModbusSlaveSimulatorTest
{
    public partial class Form1 : Form
    {
        class AppData
        {
            public string BindIp = "0.0.0.0";
            public ushort BindPort = 502;
            public byte SlaveCount = 9;
            public bool SimulationEnable = true;
            public int SimulationFreq = 1000;
            public string SimulationUnitId = "1,2,3,4,5,6,7,8,9";
            public ushort SimulationRegisterMax = 1000;
            public ushort SimulationStep = 1;
        }

        TcpListener modbusListener;
        List<IModbusSlave> listSlave = new List<IModbusSlave>();
        IModbusSlaveNetwork modbusSlaveNetwork = null;
        Dictionary<ushort, bool> dictSlaves = new Dictionary<ushort, bool>();
        //数据仿真
        ushort uValue = 0;
        ushort uStep = 1;
        AppData appData = new AppData();
        IModbusFactory factory = new ModbusFactory();

        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            //创建通讯绑定端口
            modbusListener = new TcpListener(IPAddress.Parse(appData.BindIp), appData.BindPort);
            modbusListener.Start();

            modbusSlaveNetwork = factory.CreateSlaveNetwork(modbusListener);

            //创建Slave设备
            for (byte i = 0; i < appData.SlaveCount; i++)
            {
                IModbusSlave slave = factory.CreateSlave((byte)(i + 1));
                listSlave.Add(slave);
                modbusSlaveNetwork.AddSlave(slave);
                dictSlaves[(ushort)(i + 1)] = true;
            }

            //接受连接
            modbusSlaveNetwork.ListenAsync();

            comboBox1.SelectedIndex = 4;
            
        }

        private void checkBox9_MouseClick(object sender, MouseEventArgs e)
        {
            CheckBox cb = sender as CheckBox;
            byte slaveId = byte.Parse(cb.Text.Replace("Slave", ""));
            if (cb.Checked)
            {
                modbusSlaveNetwork.AddSlave(listSlave[slaveId - 1]);
                dictSlaves[slaveId] = true;
            }
            else
            {
                modbusSlaveNetwork.RemoveSlave(slaveId);
                dictSlaves.Remove(slaveId);
            }
        }


        private void checkBox10_CheckedChanged(object sender, EventArgs e)
        {
            timer1.Enabled = checkBox10.Checked;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            bool[] vb = new bool[appData.SimulationRegisterMax];
            ushort[] vu = new ushort[appData.SimulationRegisterMax];
            for (int i = 0; i < appData.SimulationRegisterMax; i++)
            {
                vu[i] = uValue;
                vb[i] = (uValue % 2 == 1) ? true : false;
            }

            foreach (var slave in listSlave)
            {
                if (!dictSlaves.ContainsKey(slave.UnitId))
                    continue;
                slave.DataStore.CoilDiscretes.WritePoints(0, vb);
                slave.DataStore.CoilInputs.WritePoints(0, vb);
                slave.DataStore.InputRegisters.WritePoints(0, vu);
                slave.DataStore.HoldingRegisters.WritePoints(0, vu);
            }

            uValue += uStep;
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            timer1.Interval = int.Parse(comboBox1.Text);
        }
    }
}

代码托管地址:PascalMing/ModbusSlaveSimulatorTest: Modbus从站仿真
编译后的程序下载:https://github.com/PascalMing/ModbusSlaveSimulatorTest/releases/tag/v20250508

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

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

相关文章

【深度学习】目标检测算法大全

目录 一、R-CNN 1、R-CNN概述 2、R-CNN 模型总体流程 3、核心模块详解 &#xff08;1&#xff09;候选框生成&#xff08;Selective Search&#xff09; &#xff08;2&#xff09;深度特征提取与微调 2.1 特征提取 2.2 网络微调&#xff08;Fine-tuning&#xff09; …

视觉-语言-动作模型:概念、进展、应用与挑战(下)

25年5月来自 Cornell 大学、香港科大和希腊 U Peloponnese 的论文“Vision-Language-Action Models: Concepts, Progress, Applications and Challenges”。 视觉-语言-动作 (VLA) 模型标志着人工智能的变革性进步&#xff0c;旨在将感知、自然语言理解和具体动作统一在一个计…

一键解锁嵌入式UI开发——LVGL的“万能配方”

面对碎片化的嵌入式硬件生态&#xff0c;LVGL堪称开发者手中的万能配方。它通过统一API接口屏蔽底层差异&#xff0c;配合丰富的预置控件&#xff08;如按钮、图表、滑动条&#xff09;与动态渲染引擎&#xff0c;让工程师无需深入图形学原理&#xff0c;效率提升肉眼可见。 L…

智慧城市综合运营管理系统Axure原型

这款Axure原型的设计理念紧紧围绕城市管理者的需求展开。它旨在打破传统城市管理中信息孤岛的局面&#xff0c;通过统一标准接入各类业务系统&#xff0c;实现城市运营管理信息资源的全面整合与共享。以城市管理者为中心&#xff0c;为其提供一个直观、便捷、高效的协同服务平台…

Qwen智能体qwen_agent与Assistant功能初探

Qwen智能体qwen_agent与Assistant功能初探 一、Qwen智能体框架概述 Qwen&#xff08;通义千问&#xff09;智能体框架是阿里云推出的新一代AI智能体开发平台&#xff0c;其核心模块qwen_agent.agent提供了一套完整的智能体构建解决方案。该框架通过模块化设计&#xff0c;将L…

可视化图解算法37:序列化二叉树-II

1. 题目 描述 请实现两个函数&#xff0c;分别用来序列化和反序列化二叉树&#xff0c;不对序列化之后的字符串进行约束&#xff0c;但要求能够根据序列化之后的字符串重新构造出一棵与原二叉树相同的树。 二叉树的序列化(Serialize)是指&#xff1a;把一棵二叉树按照某种遍…

C++GO语言微服务和服务发现②

01 创建go-micro项目-查看生成的 proto文件 02 创建go-micro项目-查看生成的main文件和handler ## 创建 micro 服务 命令&#xff1a;micro new --type srv test66 框架默认自带服务发现&#xff1a;mdns。 使用consul服务发现&#xff1a; 1. 初始consul服务发现&…

【Web前端开发】CSS基础

2.CSS 2.1CSS概念 CSS是一组样式设置的规则&#xff0c;称为层叠样式表&#xff0c;用于控制页面的外观样式。 使用CSS能够对网页中元素位置的排版进行像素控制&#xff0c;实现美化页面的效果&#xff0c;也能够做到页面的样式和结构分离。 2.2基本语法 通常都是&#xff…

Git实战经验分享:深入掌握git commit --amend的进阶技巧

一、工具简介 git commit --amend是Git版本控制系统的核心补救命令&#xff0c;主要用于修正最近一次提交的元数据。该命令不会产生新的提交记录&#xff0c;而是通过覆盖原提交实现版本历史的整洁性&#xff0c;特别适合在本地仓库进行提交优化。 二、核心应用场景 提交信息…

PTA:jmu-ds-最短路径

给定一个有向图&#xff0c;规定源点为0&#xff0c;求源点0到其他顶点最短路径。###你要实现的 函数接口定义&#xff1a; void Dijkstra(MGraph g,int v);//源点v到其他顶点最短路径 裁判测试程序样例&#xff1a; #include <stdio.h> #include <iostream> …

WEB UI自动化测试之Pytest框架学习

文章目录 前言Pytest简介Pytest安装Pytest的常用插件Pytest的命名约束Pytest的运行方式Pytest运行方式与unittest对比主函数运行命令行运行执行结果代码说明 pytest.ini配置文件方式运行&#xff08;推荐&#xff09;使用markers标记测试用例 pytest中添加Fixture&#xff08;测…

深入理解 iOS 开发中的 `use_frameworks!`

在使用 CocoaPods 管理 iOS 项目依赖时&#xff0c;开发者经常会在 Podfile 文件中看到一个配置选项&#xff1a;use_frameworks!。本文将详细介绍这个配置选项的含义&#xff0c;以及如何决定是否在项目中使用它。 一、什么是 use_frameworks! 在 CocoaPods 中引入第三方库时…

矩阵置零算法讲解

矩阵置零算法讲解 一、问题描述 给定一个 (m \times n) 的矩阵,如果一个元素为 (0) ,则将其所在行和列的所有元素都设为 (0) 。要求使用原地算法,即在不使用额外矩阵空间的情况下完成操作。 二、解题思路 暴力解法 最直观的想法是遍历矩阵,当遇到 (0) 元素时,直接将其…

二本计算机,毕业=失业?

我嘞个豆&#xff0c;二本计算机&#xff0c;毕业即失业&#xff1f;&#xff01; 今天咱们聊聊普通院校计算机专业的学生未来的发展方向。有些话可能不太中听&#xff0c;但希望大家能理性看待。 首先得承认&#xff0c;对于普通双非和二本的学生来说&#xff0c;就业率加上…

[docker基础二]NameSpace隔离实战

目录 一 实战目的 二 基础知识 1)dd 命令详解 2)mkfs命令详解 3)df命令详解 4)mount 命令详解 5)unshare命令详解 三 实战操作一(PID隔离) 四 实战操作二(MOunt隔离) 1&#xff09;创建 Mount 隔离进程 2&#xff09;在新进程里边&#xff0c;创建空白文件&#…

Day22打卡-复习

复习日 仔细回顾一下之前21天的内容&#xff0c;没跟上进度的同学补一下进度。 作业&#xff1a; 自行学习参考如何使用kaggle平台&#xff0c;写下使用注意点&#xff0c;并对下述比赛提交代码 泰坦尼克号人员生还预测https://www.kaggle.com/competitions/titanic/overview K…

uniapp + vue3 + 京东Nut动作面板组件:实现登录弹框组件(含代码、案例、小程序截图)

uniapp + vue3 + 京东Nut动作面板组件:实现登录弹框组件(含代码、案例、小程序截图) 代码示下,不再赘述。 动作面板组件:https://nutui-uniapp.netlify.app/components/feedback/actionsheet.html 项目背景 业务需求 描述: uniapp + vue3 + 京东Nut框架:实现登录弹框组…

C++类和对象--中阶

C类和对象中阶 01. 类的6个默认成员函数 在 C 中&#xff0c;类有 6 个特殊的默认成员函数&#xff08;不是 6 个构造函数&#xff09;&#xff0c;它们会在特定情况下由编译器自动生成。包括构造函数&#xff0c;析构函数&#xff0c;拷贝构造和赋值运算符重载&#xff0c;取…

数据签名在区块链中的独特应用与挑战

随着信息技术的飞速发展&#xff0c;分布式系统因其高效、可靠、可扩展等显著优点&#xff0c;在众多领域得到了极为广泛的应用。分布式系统通过网络将多个独立的计算节点连接在一起&#xff0c;协同完成复杂的任务&#xff0c;这种架构使得系统具备了强大的容错能力和负载均衡…

数据可视化大屏——物流大数据服务平台(二)

代码分析&#xff1a; 物流大数据平台代码分析 这是一个基于 Bootstrap 和 ECharts 构建的物流大数据平台前端页面&#xff0c;设计采用了经典的三栏布局&#xff0c;主要展示河南省及全国的物流数据可视化内容。下面从多个维度进行分析&#xff1a; 1. 页面结构分析 整体采…