2019.10.26 更新第三篇文章原创 Modbus的(NModbus)研究(电表、水表等RS485/RS232等)——实现RTU/TCP通信连接(三)
前言:最近一个月的任务用nmodbus实现rtu/tcp通信连接,前期通过翻看书本 杨更更的Modbus软件开发指南 根据里面的指导来完成limodbus和numodbus 但是效果并没有太理想,详见上一篇文章,后来在一位博友的帮助下了解到NModbus API文档,通读文档后,根据文档说明及实例源代码完成了自己的工作,实现了RTU/TCP的通信。
一、首先放出参考的有价值的NModbus网站
1.modbus tools 全英解释 https://modbustools.com/download.html 官方 详细解释说明
2.Modbus/Nmodbus 中文繁体版 http://www.icpdas.com/products/PAC/i-8000/modbus_c.htm 官方
3.我所用的测试连通的工具
salve poll https://download.csdn.net/download/lsc_hei/10709595以及
vspd https://download.csdn.net/download/lsc_hei/10729508工具
测试串口连通性工具 https://download.csdn.net/download/lsc_hei/10742111
TCp测试网络是否连通,才测试程序的正确性https://download.csdn.net/download/lsc_hei/10745748
十六进制转float https://download.csdn.net/download/lsc_hei/10742108
4.nmodbus api说明文档 即本人根据完成的 https://download.csdn.net/download/lsc_hei/10750678
二、实现RTU的通信连接
以本人所使用的VS2013做法示范;
1.首先新建一个工程点击工具下拉菜单找到--管理NuGet程序包(也可能没有少一项,搞搞就出来了,很简单)--然后搜索你需要的包(nmodbus4,记得选择nuget 不然可能找不到)--点击安装即可。安装完成后引入命名控件using Modbus.Deice 然后去创建你的winform就行了,因为我是用winform,其他的类似,请自行比对。
我根据的是master和slave端 即主站和从站,我根据官方示例是分开的,我合在一起使用了。在本次中电表相当于从站用于创建数据仓库和监听主站;主站:即pc端 写的程序,用来发送获取数据的指令和得到数据进行后续处理。
*/*有了nmodbus以后,打开串口,通过一系列输入进行参数设定,直接可以读取寄存器里面的数据,定义初始化如下:
master端:
public SerialPort serialPort1 = new SerialPort("COM3");
//串口的初始化如下
serialPort1.BaudRate = 9600;
serialPort1.DataBits = 8;
serialPort1.Parity = Parity.Even;
serialPort1.StopBits = StopBits.One;
serialPort1.Open();
public IModbusSerialMaster master= ModbusSerialMaster.CreateRtu(serialPort1);
slave端:
byte slaveID = 148;
SerialPort serialPort = new SerialPort();
serialPort.BaudRate = 9600;
serialPort.DataBits = 8;
serialPort.Parity = Parity.Even;
serialPort.StopBits = StopBits.One;
//serialPort.Open();
slave = ModbusSerialSlave.CreateRtu(slaveID, serialPort);
//2.0当slave收到master命令时触发事件,取得modbus命令封装包,可拆解做特殊应用
slave.ModbusSlaveRequestReceived += new EventHandler
//创建数据仓库
slave.DataStore = Modbus.Data.DataStoreFactory.CreateDefaultDataStore();
//写入到AO D0 不过暂时没用到
// slave.DataStore.DataStoreWrittenTo += new EventHandler
//开启监听
slave.Listen();
注意端口,波特率,奇偶校验,停止位,数据位 很重要的,一定要和你测试的那个硬件相匹配,事先和那个硬件的提供方联系好
基本功能如下;
读取数据函数:
byte slaveId = salveID; 很重要,一定要知道,不能瞎猜测
ushort startAddress = 0000;//表示从哪开始读
ushort numRegisters = 0002; //表示读多少
ushort[] registers = master.ReadHoldingRegisters(slaveId, startAddress, numRegisters);
//读取寄存器数据到register数组中
然后对数据进行处理,得到的数据是十进制单位,看返回的有几个字节,就是几个十进制,然后按照自己的需求搞
我所运用示例
txtReceive.Text += "得到的十进制为" + holdingregister[0].ToString() + "和"+ holdingregister[1].ToString() + ";
同时 将得到的十进制转化为16进制然后再转化为float进行输出,看个人需求
string hexString = Convert.ToString(holdingregister[0], 16) + Convert.ToString(holdingregister[1], 16);
uint num = uint.Parse(hexString, System.Globalization.NumberStyles.AllowHexSpecifier);
byte[] floatVals = BitConverter.GetBytes(num);
float f = BitConverter.ToSingle(floatVals, 0);
txtReceive.Text += "转换成的float数为:" + f;
最后如果需要循环执行的话,后面再加一个timer 里面设置相应的循环参数即可。本处不在示例。
如图所示的串口测试连通性软件
[发送]94 03 00 00 00 02 D9 0E
[接收]94 03 04 3D 8F 5C 29 FB A3
说明:设备地址(1字节)+功能号(1)+寄存器起始地址(2字节)+读取的寄存器数(2)+CRC校验
说明:设备地址(1字节)+功能号(1)+返回的字节数+数据1+数据2+...+等于字节数+CRC校验
返回的字节数=2*读取的寄存器数
四、在官方示例文档中,将slave和master进行分开演示,测试连通时也没有成功过,但是代码逻辑与功能都是很完善的,根据思考,我将master 和slave进行整合在winform中,其实只要连接一次串口打开一次串口就可以,然后根据参数设置连接的rtu对象,master端就只需要打开创建master即可,slave在创建成功后需要多一个数据仓库和事件监听,当得到mster端的请求时触发事件,查询数据的得到结果。 然后在一个button的触发事件下因为rtu连接分为这样基本上就能连通硬件,基本上也没有什么忽略的。在后面我会放上自己的源代码。
源代码地址:已完成https://download.csdn.net/download/lsc_hei/10751245
https://download.csdn.net/download/lsc_hei/10750738
对了这是官方示例的demo拿好各位https://download.csdn.net/download/lsc_hei/10750717