Modbus协议时应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络/串口和其它设备之间可以进行通信。它已经成为了一种工业标准。有了这个通信协议,不同的厂商生成的控制设备就可以连城工业网络,进行集中监控。
本文实现需要借用一个开源的NModbus库来完成,通过在菜单栏,工具-----NuGet包管理器-----管理解决方案的NuGet程序包,安装NModbus的开源库。
本次实例的基本框架和实现效果如下所示:
可自动识别当前设备的可用串口。
Modbus RTU通信的具体的实现如下:
View Code
在线程中对控件的属性进行操作可能会出现代码异常,可以使用Invoke委托方法完成相应的操作:
public void SetMsg(string msg) { richTextBox1.Invoke(new Action(() => { richTextBox1.AppendText(msg); })); }
在进行自动读/写操作时,为避免多次点击按键控件,多次重复建立新线程;在进入自动读写线程中时,将对应的按键控件失能,等待停止读写操作时再使能:
private void AutomaticTest() { AutoFlag = true; button1.Enabled = false; InitSerialPortParameter(); master = ModbusSerialMaster.CreateRtu(port); Task.Factory.StartNew(() => { //初始化串口参数 while (AutoFlag) { try { ExecuteFunction(); } catch (Exception) { MessageBox.Show("初始化异常"); } Thread.Sleep(500); } }); }
自动获取当前设备的可用串口实现如下:
#region 串口下拉列表刷新 /// <summary> /// 刷新下拉列表显示 /// </summary> private void GetSerialLstTb1() { //清除cmb_portname显示 cmb_portname.SelectedIndex = -1; cmb_portname.Items.Clear(); //获取串口列表 string[] serialLst = SerialPort.GetPortNames(); if (serialLst.Length > 0) { //取串口进行排序 Array.Sort(serialLst); //将串口列表输出到cmb_portname cmb_portname.Items.AddRange(serialLst); cmb_portname.SelectedIndex = 0; } } /// <summary> /// 消息处理 /// </summary> /// <param name="m"></param> protected override void WndProc(ref Message m) { switch (m.Msg) //判断消息类型 { case WM_DEVICE_CHANGE: //设备改变消息 { GetSerialLstTb1(); //设备改变时重新花去串口列表 } break; } base.WndProc(ref m); } #endregion
对本次实例进行测试需要使用到串口模拟软件,串口模拟器可以到网上下载,也可以通过以下链接进行下载:
链接:https://pan.baidu.com/s/1XRUIqTqZ9rwnYowyVyn4cQ
提取码:xy4m
Modbus从站模拟器下载链接:
链接:https://pan.baidu.com/s/1Bf0Qg50_d-XYlwQfzEY8ag
提取码:06i9
Modbus从站需要完成一下两步操作:
一、菜单栏Connection-----Connect
二、菜单栏Setup-----Slave Definition
最后需要运行自己创建的Modbus RTU Master上位机,完成相应的配置:
实现的最终效果: