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上位机,完成相应的配置:
实现的最终效果: