【C#】CS学习之Modbus通讯

打印 上一主题 下一主题

主题 957|帖子 957|积分 2871


摘要
本文详细描述了如安在在C#的Winform应用步伐中利用NModbus库实现Modbus通讯,包罗读取保持寄存器、以及相应的UI界面筹划和变乱处置惩罚。

媒介

​应用场景

   Modbus 从站广泛应用于工业自动化领域:
1、传感器数据采集(如温度、压力等)
2、执行器控制(如电机、阀门等)
3、设备监控与故障诊断。
  Modbus 从站(Slave)是 Modbus 通讯协议中的响应设备,负责接收并执行来自主站(Master)的请求。
   Modbus 从站是被动设备,它不能自动发起通讯,只能响应主站的请求。从站的主要功能包罗:
1、接收主站的指令(如读取数据或执行操作)。
2、执行相应的操作(如读取寄存器值或设置参数)。
3、返反响应数据或错误码给主站。
  通讯模式

   Modbus 从站支持多种通讯模式:
​1、Modbus RTU/ASCII:通过串口(如 RS485)举行通讯,从站监听串口链路并响应主站指令。
​2、Modbus TCP:通过以太网举行通讯,从站作为服务器监听 TCP 端口(默认 502 端口)并处置惩罚客户端请求。
  ​寄存器范例

   Modbus 从站通常管理四种范例的寄存器:
1、线圈(Coils):可读写的二进制状态(如开关状态)。
2、离散输入(Discrete Inputs):只读的二进制状态。
3、保持寄存器(Holding Registers):可读写的16位数据。
4、输入寄存器(Input Registers):只读的16位数据。
  实现步骤

   1、创建TcpListener并启动 侦听
2、创建Modbus从站数据存储
3、初始化数据
4、创建Modbus从站
5、创建Modbus TCP从站网络
6、添加从站到网络
7、异步侦听网络
  运行结果


代码

Frm_ModbusService

  1.     public partial class Frm_ModbusService : Form
  2.     {
  3.         #region 字段
  4.         //定时器
  5.         Timer timer = null;
  6.         ModbusService modbusService = null;
  7.         #endregion
  8.         #region 构造函数、初始化
  9.         public Frm_ModbusService()
  10.         {
  11.             InitializeComponent();
  12.             CenterToParent();
  13.             CenterToScreen();
  14.         }
  15.         private void ModbusService_Load(object sender, EventArgs e)
  16.         {
  17.             Initialize();
  18.         }
  19.         private void ModbusService_FormClosing(object sender, FormClosingEventArgs e)
  20.         {
  21.             modbusService.Stop();
  22.         }
  23.         #endregion
  24.         /// <summary>
  25.         /// 初始化控件状态
  26.         /// </summary>
  27.         public void InitializeControlsState()
  28.         {
  29.             tbx_IPAddress.Text = modbusService.IpAddress.ToString();
  30.             tbx_OpenPort.Text = modbusService.Port.ToString();
  31.             tbx_StartAddress.Text = modbusService.StartAddress.ToString();
  32.             tbx_SlaveID.Text = modbusService.SlaveId.ToString();  
  33.         }
  34.         /// <summary>
  35.         /// 初始化
  36.         /// </summary>
  37.         public void Initialize()
  38.         {
  39.             modbusService = new ModbusService();
  40.             modbusService.MessageUpdateHandler += OnUpdataMessage;
  41.             InitializeControlsState();
  42.             UpdataControlsState(modbusService.IsRunning);
  43.             timer = new Timer();
  44.             timer.Interval = 100;
  45.             timer.Tick += Timer_Tick;
  46.             dataGridView.Columns[0].Width = 100;
  47.             dataGridView.Columns[1].Width = 100;
  48.             dataGridView.Columns[0].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
  49.             dataGridView.Columns[1].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
  50.             dataGridView.RowHeadersVisible = false;
  51.             
  52.             //10行
  53.             dataGridView.Rows.Add(new object[] { 0, 0});
  54.             dataGridView.Rows.Add(new object[] { 1, 0 });
  55.             dataGridView.Rows.Add(new object[] { 2, 0 });
  56.             dataGridView.Rows.Add(new object[] { 3, 0 });
  57.             dataGridView.Rows.Add(new object[] { 4, 0 });
  58.             dataGridView.Rows.Add(new object[] { 5, 0 });
  59.             dataGridView.Rows.Add(new object[] { 6, 0 });
  60.             dataGridView.Rows.Add(new object[] { 7, 0 });
  61.             dataGridView.Rows.Add(new object[] { 8, 0 });
  62.             dataGridView.Rows.Add(new object[] { 9, 0 });
  63.         }
  64.         /// <summary>
  65.         /// 定时器方法
  66.         /// </summary>
  67.         private void Timer_Tick(object sender, EventArgs e)
  68.         {
  69.             var array = modbusService.DataStore.HoldingRegisters.ReadPoints(modbusService.StartAddress, 10);
  70.             for (int i = 0; i < array.Length; i++)
  71.             {
  72.                 dataGridView.Rows[i].Cells[0].Value = (modbusService.StartAddress+ i);
  73.                 dataGridView.Rows[i].Cells[1].Value = array[i];
  74.             }
  75.         }
  76.         /// <summary>
  77.         /// 启动按钮
  78.         /// </summary>
  79.         private void btn_Start_Click(object sender, EventArgs e)
  80.         {
  81.             try
  82.             {
  83.                 if (!modbusService.IsRunning)
  84.                 {
  85.                     modbusService.Start();
  86.                     timer.Start();
  87.                     UpdataControlsState(modbusService.IsRunning);
  88.                 }
  89.                 else
  90.                 {
  91.                     modbusService.Stop();
  92.                     timer.Stop();
  93.                     UpdataControlsState(modbusService.IsRunning);
  94.                     UpdataMessage("Modbus服务停止");
  95.                 }
  96.             }
  97.             catch (Exception ex)
  98.             {
  99.                 modbusService.Stop();
  100.                 timer.Stop();
  101.                 UpdataControlsState(modbusService.IsRunning);
  102.                 UpdataMessage($"Modbus服务异常停止:{ex.Message}");
  103.             }
  104.         }
  105.         /// <summary>
  106.         /// 更新消息
  107.         /// </summary>
  108.         private void UpdataMessage(string message)
  109.         {
  110.             tbx_Output.BeginInvoke(new Action(() =>
  111.             {
  112.                 if (tbx_Output.Lines.Length>100)
  113.                 {
  114.                     tbx_Output.Clear();
  115.                 }
  116.                 tbx_Output.AppendText($"{DateTime.Now.ToString()}】{message}\r\n");
  117.             }));
  118.         }
  119.         /// <summary>
  120.         /// 更新消息
  121.         /// </summary>
  122.         private void OnUpdataMessage(object sender, string message)
  123.         {
  124.             UpdataMessage(message);
  125.         }
  126.         /// <summary>
  127.         /// 更新控件状态
  128.         /// </summary>
  129.         private void UpdataControlsState(bool isRunning)
  130.         {
  131.             if (isRunning)
  132.             {
  133.                 tbx_IPAddress.Enabled = false;
  134.                 tbx_OpenPort.Enabled = false;
  135.                 tbx_SlaveID.Enabled = false;
  136.                 btn_Start.Text = "关闭";
  137.             }
  138.             else
  139.             {
  140.                 tbx_IPAddress.Enabled = true;
  141.                 tbx_OpenPort.Enabled = true;
  142.                 tbx_SlaveID.Enabled = true;
  143.                 btn_Start.Text = "启动";
  144.             }
  145.         }
  146.         #region 参数变更
  147.         /// <summary>
  148.         /// IP地址变更
  149.         /// </summary>
  150.         private void tbxIPAddress_TextChanged(object sender, EventArgs e)
  151.         {
  152.             if (IPAddress.TryParse(tbx_IPAddress.Text,out IPAddress result))
  153.             {
  154.                 modbusService.IpAddress = result;
  155.             }
  156.             else
  157.             {
  158.                 tbx_IPAddress.Text = modbusService.IpAddress.ToString();
  159.             }
  160.         }
  161.         /// <summary>
  162.         /// 端口变更
  163.         /// </summary>
  164.         private void tbxOpenPort_TextChanged(object sender, EventArgs e)
  165.         {
  166.             if (ushort.TryParse(tbx_OpenPort.Text, out ushort result))
  167.             {
  168.                 modbusService.Port = result;
  169.             }
  170.             else
  171.             {
  172.                 tbx_OpenPort.Text = modbusService.Port.ToString();
  173.             }
  174.         }
  175.         /// <summary>
  176.         /// 起始地址变更
  177.         /// </summary>
  178.         private void tbx_StartAddress_TextChanged(object sender, EventArgs e)
  179.         {
  180.             if (ushort.TryParse(tbx_StartAddress.Text, out ushort result))
  181.             {
  182.                 modbusService.StartAddress = result;
  183.             }
  184.             else
  185.             {
  186.                 tbx_StartAddress.Text = modbusService.StartAddress.ToString();
  187.             }
  188.         }
  189.         /// <summary>
  190.         /// 站ID变更
  191.         /// </summary>
  192.         private void tbx_SlaveID_TextChanged(object sender, EventArgs e)
  193.         {
  194.             if (byte.TryParse(tbx_SlaveID.Text, out byte result))
  195.             {
  196.                 modbusService.SlaveId = result;
  197.             }
  198.             else
  199.             {
  200.                 tbx_SlaveID.Text = modbusService.SlaveId.ToString();
  201.             }
  202.         }
  203.         #endregion
  204.     }
  205. }
复制代码
ModbusService

  1. public class ModbusService
  2. {
  3.     #region 字段、属性
  4.     public event EventHandler<string> MessageUpdateHandler;
  5.     private IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
  6.     private int port = 502;                            //端口
  7.     private byte slaveId = 1;                    // 从站地址
  8.     private ushort startAddress = 0;    //起始地址
  9.     private bool isRunning = false;     //运行状态
  10.     private TcpListener tcpListener = null;                            //创建Modbus服务器
  11.     private DefaultSlaveDataStore dataStore = null;    //默认从站数据存储
  12.     private ModbusFactory factory = null;                            //Bodbus工厂
  13.     private IModbusSlave slave = null;                            //modbus从站
  14.     IModbusTcpSlaveNetwork slaveNetwork = null;            //ModbusTcp从站网络
  15.     public IPAddress IpAddress { get => ipAddress; set => ipAddress = value; }
  16.     public int Port { get => port; set => port = value; }
  17.     public byte SlaveId { get => slaveId; set => slaveId = value; }
  18.     public ushort StartAddress { get => startAddress; set => startAddress = value; }
  19.     public bool IsRunning { get => isRunning; set => isRunning = value; }
  20.     public TcpListener TcpListener { get => tcpListener; set => tcpListener = value; }
  21.     public DefaultSlaveDataStore DataStore { get => dataStore; set => dataStore = value; }
  22.     public ModbusFactory Factory { get => factory; set => factory = value; }
  23.     public IModbusSlave Slave { get => slave; set => slave = value; }
  24.     public IModbusTcpSlaveNetwork SlaveNetwork { get => slaveNetwork; set => slaveNetwork = value; }
  25.     #endregion
  26.     public ModbusService() {}
  27.     /// <summary>
  28.     /// 初始化从站数据存储
  29.     /// </summary>
  30.     private void InitializeDataStore(DefaultSlaveDataStore dataStore)
  31.     {
  32.         // 初始化保持寄存器
  33.         dataStore.HoldingRegisters.WritePoints(0, new ushort[] { 0 });
  34.         // 初始化输入寄存器
  35.         dataStore.InputRegisters.WritePoints(0, new ushort[] { 0 });
  36.         // 初始化线圈
  37.         dataStore.CoilDiscretes.WritePoints(0, new bool[] { false });
  38.         // 初始化离散输入
  39.         dataStore.CoilInputs.WritePoints(0, new bool[] { false });
  40.     }
  41.     /// <summary>
  42.     /// 启动按钮
  43.     /// </summary>
  44.     public void Start()
  45.     {
  46.         try
  47.         {
  48.             if (!IsRunning)
  49.             {
  50.                 // 创建TcpListener并启动
  51.                 TcpListener = new TcpListener(IpAddress, Port);
  52.                 //启动侦听
  53.                 TcpListener.Start();
  54.                 // 创建Modbus从站数据存储
  55.                 DataStore = new DefaultSlaveDataStore();
  56.                 // 初始化数据
  57.                 InitializeDataStore(DataStore);
  58.                 // 创建Modbus从站
  59.                 Factory = new ModbusFactory();
  60.                 Slave = Factory.CreateSlave(1, DataStore);
  61.                 // 创建Modbus TCP从站网络
  62.                 SlaveNetwork = Factory.CreateSlaveNetwork(TcpListener);
  63.                 // 添加从站到网络
  64.                 SlaveNetwork.AddSlave(Slave);
  65.                 //异步侦听网络
  66.                 SlaveNetwork.ListenAsync();
  67.                 IsRunning = true;
  68.                 OnUpdataMessage("Modbus服务启动");
  69.             }
  70.         }
  71.         catch (Exception ex)
  72.         {
  73.             Stop();
  74.             OnUpdataMessage($"Modbus服务异常停止:{ex.Message}");
  75.         }
  76.     }
  77.     public void Stop()
  78.     {
  79.         TcpListener?.Stop();
  80.         SlaveNetwork?.Dispose();
  81.         DataStore = null;
  82.         Factory = null;
  83.         Slave = null;
  84.         IsRunning = false;
  85.     }
  86.     /// <summary>
  87.     /// 消息更新
  88.     /// </summary>
  89.     private void OnUpdataMessage(string message)
  90.     {
  91.         MessageUpdateHandler?.Invoke(this,message);
  92.     }
  93. }
复制代码
结语

总结来说,Modbus 从站是 Modbus 网络中的关键构成部分,负责响应主站指令并执行相应操作。广泛应用于工业自动化和设备控制。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

忿忿的泥巴坨

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表