关于把modbus rtu协议用modbus tcp代替

bobiji 2020-07-07 02:47:28
我原先用vb做了一个窗口程序,使用mscomm控件,电脑上连232通过分配器转成485连到现场阀门来与阀门通讯,现在我想把232的部分用以太网来代替,通过通讯模块转成485在连接现场来通讯,想请教一下大致该怎么来实现,是要把mscomm控件换成winsock吗,以太网通讯没有接触过,所以不太了解要做哪些工作
...全文
2888 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
ba_wang_mao 2020-07-08
  • 打赏
  • 举报
回复
引用 2 楼 bobiji 的回复:
引用 1 楼 weixin_41766621 的回复:
通讯部分更改,内容协议不变,建议使用NModbus等第三方封装好的Modbus协议库.具体数据解析及处理部分移植下就好了.
那还需要使用到mscomm控件吗,我是在vb6.0上编写的,初始化的话需不需要改成ip地址的初始化,还是原来9600,n,8,1这种类型串口的初始化也可以


肯定不能用mscomm控件呀!因为mscomm控件是针对串口通信滴!
要使用以太网的控件。

改动的大致方向如下:
1、建议不要使用VB6开发,建议使用VB.NET开发。
2、mscomm控件替换为VB.NET中的以太网控件。
3、MODBUS-RTU中的报文结尾的CRC16校验码删除,因为以太网通信通信已经有了校验码。

下面是我在安桌下写的MODBUS-TCP主站代码,你参考一下。


[code=java]package com.example.modbustcp;

import usertype.MODBUS_QUEUE_TYPE;


public class Modbus
{
public Modbus() {

}

static public void ReadCoilRegisters(MODBUS_QUEUE_TYPE ptcb)
{
short ByteCount;
MODBUS_QUEUE_TYPE tempQueue = new MODBUS_QUEUE_TYPE();

tempQueue.Data[0] = GlobalVar.TransactionIdent_H; //事务处理标识符高字节
tempQueue.Data[1] = GlobalVar.TransactionIdent_L; //事务处理标识符低字节
tempQueue.Data[2] = (byte) (GlobalVar.ProtocolIdent >> 0x08); //协议标识符H =0 表示MODBUS协议
tempQueue.Data[3] = (byte) (GlobalVar.ProtocolIdent & 0xFF); //协议标识符L =0 表示MODBUS协议
tempQueue.Data[4] = 0x00; //长度H(从本字节下一个到最后)
tempQueue.Data[5] = 0x06; //长度L(从本字节下一个到最后)
tempQueue.Data[6] = GlobalVar.UnitIdent; //单元标识符
//----------------------------------------------------------------------------------
tempQueue.Data[7] = 0x01; //功能码
tempQueue.Data[8] = (byte) (ptcb.StartAddr >> 0x08); //起始地址H
tempQueue.Data[9] = (byte) (ptcb.StartAddr & 0xFF); //起始地址L
tempQueue.Data[10] = (byte) (ptcb.RegisterAmount >> 0x08); //寄存器数量H
tempQueue.Data[11] = (byte) (ptcb.RegisterAmount & 0xFF); //寄存器数量L
//----------------------------------------------------------------------------------
tempQueue.Func = 0x01;
tempQueue.StartAddr = ptcb.StartAddr;
tempQueue.RegisterAmount = ptcb.RegisterAmount;

ByteCount = (short)(ptcb.RegisterAmount >> 3);
if ((ptcb.RegisterAmount & 0x07) != 0)
ByteCount++;
tempQueue.ByteCount = ByteCount;
tempQueue.SendCount = 12;
tempQueue.RepeatCount = 0x03;
GlobalVar.ModbusQueue.In_Queue(tempQueue);

}

static public void ReadDiscreteRegisters(MODBUS_QUEUE_TYPE ptcb)
{
short ByteCount;
MODBUS_QUEUE_TYPE tempQueue = new MODBUS_QUEUE_TYPE();

tempQueue.Data[0] = GlobalVar.TransactionIdent_H; //事务处理标识符高字节
tempQueue.Data[1] = GlobalVar.TransactionIdent_L; //事务处理标识符低字节
tempQueue.Data[2] = (byte) (GlobalVar.ProtocolIdent >> 0x08); //协议标识符H =0 表示MODBUS协议
tempQueue.Data[3] = (byte) (GlobalVar.ProtocolIdent & 0xFF); //协议标识符L =0 表示MODBUS协议
tempQueue.Data[4] = 0x00; //长度H(从本字节下一个到最后)
tempQueue.Data[5] = 0x06; //长度L(从本字节下一个到最后)
tempQueue.Data[6] = GlobalVar.UnitIdent; //单元标识符
//----------------------------------------------------------------------------------
tempQueue.Data[7] = 0x02; //功能码
tempQueue.Data[8] = (byte) (ptcb.StartAddr >> 0x08); //起始地址H
tempQueue.Data[9] = (byte) (ptcb.StartAddr & 0xFF); //起始地址L
tempQueue.Data[10] = (byte) (ptcb.RegisterAmount >> 0x08); //寄存器数量H
tempQueue.Data[11] = (byte) (ptcb.RegisterAmount & 0xFF); //寄存器数量L
//----------------------------------------------------------------------------------
tempQueue.Func = 0x02;
tempQueue.StartAddr = ptcb.StartAddr;
tempQueue.RegisterAmount = ptcb.RegisterAmount;

ByteCount = (short)(ptcb.RegisterAmount >> 3);
if ((ptcb.RegisterAmount & 0x07) != 0)
ByteCount++;
tempQueue.ByteCount = ByteCount;
tempQueue.SendCount = 12;
tempQueue.RepeatCount = 0x03;
GlobalVar.ModbusQueue.In_Queue(tempQueue);
}

//当读取125个寄存器时系统本刊崩溃,目前程序最大只能读取120个寄存器
static public void ReadInputRegisters(MODBUS_QUEUE_TYPE ptcb)
{
MODBUS_QUEUE_TYPE tempQueue = new MODBUS_QUEUE_TYPE();

tempQueue.Data[0] = GlobalVar.TransactionIdent_H; //事务处理标识符高字节
tempQueue.Data[1] = GlobalVar.TransactionIdent_L; //事务处理标识符低字节
tempQueue.Data[2] = (byte) (GlobalVar.ProtocolIdent >> 0x08); //协议标识符H =0 表示MODBUS协议
tempQueue.Data[3] = (byte) (GlobalVar.ProtocolIdent & 0xFF); //协议标识符L =0 表示MODBUS协议
tempQueue.Data[4] = 0x00; //长度H(从本字节下一个到最后)
tempQueue.Data[5] = 0x06; //长度L(从本字节下一个到最后)
tempQueue.Data[6] = GlobalVar.UnitIdent; //单元标识符
//----------------------------------------------------------------------------------
tempQueue.Data[7] = 0x04; //功能码
tempQueue.Data[8] = (byte) (ptcb.StartAddr >> 0x08); //起始地址H
tempQueue.Data[9] = (byte) (ptcb.StartAddr & 0xFF); //起始地址L
tempQueue.Data[10] = (byte) (ptcb.RegisterAmount >> 0x08); //寄存器数量H
tempQueue.Data[11] = (byte) (ptcb.RegisterAmount & 0xFF); //寄存器数量L
//----------------------------------------------------------------------------------
tempQueue.Func = 0x04;
tempQueue.StartAddr = ptcb.StartAddr;
tempQueue.RegisterAmount = ptcb.RegisterAmount;
tempQueue.ByteCount = (short)(ptcb.RegisterAmount << 0x01);
tempQueue.SendCount = 12;
tempQueue.RepeatCount = 0x03;
GlobalVar.ModbusQueue.In_Queue(tempQueue);
}

//当读取125个寄存器时系统本刊崩溃,目前程序最大只能读取120个寄存器
static public void ReadHoldingRegisters(MODBUS_QUEUE_TYPE ptcb)
{
MODBUS_QUEUE_TYPE tempQueue = new MODBUS_QUEUE_TYPE();

tempQueue.Data[0] = GlobalVar.TransactionIdent_H; //事务处理标识符高字节
tempQueue.Data[1] = GlobalVar.TransactionIdent_L; //事务处理标识符低字节
tempQueue.Data[2] = (byte) (GlobalVar.ProtocolIdent >> 0x08); //协议标识符H =0 表示MODBUS协议
tempQueue.Data[3] = (byte) (GlobalVar.ProtocolIdent & 0xFF); //协议标识符L =0 表示MODBUS协议
tempQueue.Data[4] = 0x00; //长度H(从本字节下一个到最后)
tempQueue.Data[5] = 0x06; //长度L(从本字节下一个到最后)
tempQueue.Data[6] = GlobalVar.UnitIdent; //单元标识符
//----------------------------------------------------------------------------------
tempQueue.Data[7] = 0x03; //功能码
tempQueue.Data[8] = (byte) (ptcb.StartAddr >> 0x08); //起始地址H
tempQueue.Data[9] = (byte) (ptcb.StartAddr & 0xFF); //起始地址L
tempQueue.Data[10] = (byte) (ptcb.RegisterAmount >> 0x08); //寄存器数量H
tempQueue.Data[11] = (byte) (ptcb.RegisterAmount & 0xFF); //寄存器数量L
//----------------------------------------------------------------------------------
tempQueue.Func = 0x03;
tempQueue.StartAddr = ptcb.StartAddr;
tempQueue.RegisterAmount = ptcb.RegisterAmount;
tempQueue.ByteCount = (short)(ptcb.RegisterAmount << 0x01);;
tempQueue.SendCount = 12;
tempQueue.RepeatCount = 0x03;
GlobalVar.ModbusQueue.In_Queue(tempQueue);
}

static public void ForceSingleCoil(MODBUS_QUEUE_TYPE ptcb , char On_Off)
{
MODBUS_QUEUE_TYPE tempQueue = new MODBUS_QUEUE_TYPE();

tempQueue.Data[0] = GlobalVar.TransactionIdent_H; //事务处理标识符高字节
tempQueue.Data[1] = GlobalVar.TransactionIdent_L; //事务处理标识符低字节
tempQueue.Data[2] = (byte) (GlobalVar.ProtocolIdent >> 0x08); //协议标识符H =0 表示MODBUS协议
tempQueue.Data[3] = (byte) (GlobalVar.ProtocolIdent & 0xFF); //协议标识符L =0 表示MODBUS协议
tempQueue.Data[4] = 0x00; //长度H(从本字节下一个到最后)
tempQueue.Data[5] = 0x06; //长度L(从本字节下一个到最后)
tempQueue.Data[6] = GlobalVar.UnitIdent; //单元标识符
// ----------------------------------------------------------------------------------
tempQueue.Data[7] = 0x05; //功能码
tempQueue.Data[8] = (byte) (ptcb.StartAddr >> 0x08); //起始地址H
tempQueue.Data[9] = (byte) (ptcb.StartAddr & 0xFF); //起始地址L
if (On_Off == 0xFF00)
tempQueue.Data[10] = (byte) 0xFF;
else
tempQueue.Data[10] = 0x00;
tempQueue.Data[11] = 0x00;
//----------------------------------------------------------------------------------
tempQueue.Func = 0x05;
tempQueue.StartAddr = ptcb.StartAddr;
tempQueue.RegisterAmount = ptcb.RegisterAmount;
tempQueue.ByteCount = 2;
tempQueue.SendCount = 12;
tempQueue.RepeatCount = 0x03;
GlobalVar.ModbusQueue.In_Queue(tempQueue);
}

static public void PresetSingleHoldingRegister(MODBUS_QUEUE_TYPE ptcb ,char Value)
{
MODBUS_QUEUE_TYPE tempQueue = new MODBUS_QUEUE_TYPE();

tempQueue.Data[0] = GlobalVar.TransactionIdent_H; //事务处理标识符高字节
tempQueue.Data[1] = GlobalVar.TransactionIdent_L; //事务处理标识符低字节
tempQueue.Data[2] = (byte) (GlobalVar.ProtocolIdent >> 0x08); //协议标识符H =0 表示MODBUS协议
tempQueue.Data[3] = (byte) (GlobalVar.ProtocolIdent & 0xFF); //协议标识符L =0 表示MODBUS协议
tempQueue.Data[4] = 0x00; //长度H(从本字节下一个到最后)
tempQueue.Data[5] = 0x06; //长度L(从本字节下一个到最后)
tempQueue.Data[6] = GlobalVar.UnitIdent; //单元标识符
//----------------------------------------------------------------------------------
tempQueue.Data[7] = 0x06; //功能码
tempQueue.Data[8] = (byte) (ptcb.StartAddr >> 0x08); //起始地址H
tempQueue.Data[9] = (byte) (ptcb.StartAddr & 0xFF); //起始地址L
tempQueue.Data[10] = (byte) (Value >> 0x08); //寄存器值H
tempQueue.Data[11] = (byte) (Value & 0xFF); //寄存器值L
//----------------------------------------------------------------------------------
tempQueue.Func = 0x06;
tempQueue.StartAddr = ptcb.StartAddr;
tempQueue.RegisterAmount = ptcb.RegisterAmount;
tempQueue.ByteCount = 2;
tempQueue.SendCount = 12;
tempQueue.RepeatCount = 0x03;
GlobalVar.ModbusQueue.In_Queue(tempQueue);
}



[/code]
bobiji 2020-07-08
  • 打赏
  • 举报
回复
引用 1 楼 weixin_41766621 的回复:
通讯部分更改,内容协议不变,建议使用NModbus等第三方封装好的Modbus协议库.具体数据解析及处理部分移植下就好了.
那还需要使用到mscomm控件吗,我是在vb6.0上编写的,初始化的话需不需要改成ip地址的初始化,还是原来9600,n,8,1这种类型串口的初始化也可以
bobiji 2020-07-08
  • 打赏
  • 举报
回复
谢谢各位给的建议
by_封爱 2020-07-08
  • 打赏
  • 举报
回复
这个东西 你tcp_client().send 就相当于 comport.write()了. 读取的话 也是通过revc给你发过来的. 串口的话 局域网很多采用这种模式.. 因为有一些数据需要实时显示 但是又不想在A电脑操作...
by_封爱 2020-07-08
  • 打赏
  • 举报
回复
不太懂... 是你以前用的串口通讯 现在想用tcp通讯 是这个意思吗? 比如 之前你这个程序只能运行在某个电脑上.. 打开串口 读取数据. 现在想采用tcp的方式, 并且想在局域网其他电脑 通过tcp的方式 来读取"串口"数据? 如果是这样..你可以上一个"串口服务器"设备,小的跟路由器差不多大小.他连硬件. 然后有网线. 自带系统 跟路由器一样 登陆之后就可以配置. 他实际上就是一个"小型中转站",有tcp方式.设置之后你局域网 就可以通过tcp_client去读取.
ziqi0716 2020-07-07
  • 打赏
  • 举报
回复
通讯部分更改,内容协议不变,建议使用NModbus等第三方封装好的Modbus协议库.具体数据解析及处理部分移植下就好了.

16,554

社区成员

发帖
与我相关
我的任务
社区描述
VB技术相关讨论,主要为经典vb,即VB6.0
社区管理员
  • VB.NET
  • 水哥阿乐
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧