Modbus TCP-C++

基于TCP协议的Modbus协议,应用于电子控制器上的一种通用语言。

ModusBus协议数据格式:

写多个寄存器

 

97 79 00 00 00 09 04 10 00 00 00 01 02 00 01

 

示例

长度

说明

备注

Map报文头

0x97

1

事务处理标识符Hi

客户机发起,服务器复制,用于事务处理配对

0x79

1

事务处理标识符Lo

0x0000

2

协议标识符号

客户机发起,服务器复制

Modbus协议 = 0.

0x0009

2

长度

从本字节下一个到最后

 

0x04

1

单元标识符

客户机发起,服务器复制

串口链路或其他总线上远程终端标识

功能码

0x10

1

功能码,读寄存器

参考标准modbus协议

数据

0x0000

2

起始地址

 

0x 0001

2

写寄存器数量

 

0x 02

1

写字节的个数

 

00 01

2

目标值

 

校验

 

数据请求回复

97 96 00 00 00 FD 04 04 FA AB 9E 41 18 7A E1 3F 94 7A E1 3F 94 0A 3D 3F 97 51 EC 3F 98 CC CD C0 6C 33 33 C0 E3 CC CD C0 EC EB 85 41 F1 D7 0A 41 E9 47 AE 41 ED EB 85 41 F1 19 9A 43 D0 E6 66 43 C9 4C CD 43 CF EB 85 41 F3 66 66 42 0F CC CD 41 C2 E6 66 44 0A 1E B8 41 FB A3 D7 42 0C CC CD 41 BC C0 00 44 0A B8 52 41 F6 5C 29 42 0F 47 AE 41 D1 C6 66 44 0A 00 00 00 00 C9 9E FF 7F C9 9E FF 7F C9 9E FF 7F C9 9E FF 7F C9 9E FF 7F C9 9E FF 7F C9 9E FF 7F C9 9E FF 7F C9 9E FF 7F 05 16 00 00 04 11 00 00 05 16 00 00 04 11 00 00 05 16 00 00 04 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0A 00 0A 00 0A 00 0A 00 04 00 04 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0F

 

示例

长度

说明

备注

Map报文头

0x97

1

事务处理标识符Hi

客户机发起,服务器复制,用于事务处理配对

0x96

1

事务处理标识符Lo

0x0000

2

协议标识符号

客户机发起,服务器复制

Modbus协议 = 0.

0x00FD

2

长度

从本字节下一个到最后

 

0x04

1

单元标识符

客户机发起,服务器复制

串口链路或其他总线上远程终端标识

功能码

0x04

1

功能码,读寄存器

参考标准modbus协议

数据

0x FA

1

字节个数

 

0x----

 

数据

校验

 

部分功能码

代码

中文名称

寄存器PLC地址

位操作/字操作

操作数量

01

读线圈状态

00001-09999

位操作

单个或多个

02

读离散输入状态

10001-19999

位操作

单个或多个

03

读保持寄存器

40001-49999

字操作

单个或多个

04

读输入寄存器

30001-39999

字操作

单个或多个

05

写单个线圈

00001-09999

位操作

单个

06

写单个保持寄存器

40001-49999

字操作

单个

15

写多个线圈

00001-09999

位操作

多个

16

写多个保持寄存器

40001-49999

字操作

多个


代码

//PlcModusTcp.h  SocketClient为第一章中的tcp通讯
#pragma once
#include "SocketClient.h"
class PlcModbusTcp
{
public:
	PlcModbusTcp();
	~PlcModbusTcp();
	ErrorCode Connect(char* ip,int port);
	ErrorCode Disconnect();
	ErrorCode ReadRegister(int addr, int len, short* buf);
	ErrorCode WriteRegister(int addr, int len, short* buf);

private:
	CRITICAL_SECTION cs;
	char m_ip[20];
	int m_port; 
	unsigned short m_cmdID;
	SocketClient m_socketClient;
};


//PlcModusTcp.cpp
#include "PlcModbusTcp.h"

/********************
  @date:2019/03/16	
  @author: yuyang
  @info:与PLC通讯Modbus协议
********************/
PlcModbusTcp::PlcModbusTcp()
{
	m_cmdID = 0;
	InitializeCriticalSection(&cs);
}


PlcModbusTcp::~PlcModbusTcp()
{
	DeleteCriticalSection(&cs);
}

ErrorCode PlcModbusTcp::Connect(char* ip, int port)
{
	ErrorCode res = ERRORCODE_OK;
	memset(m_ip, 0, 20);
	strcpy(m_ip, ip);
	m_port = port;
	res=m_socketClient.Connect(m_ip, port, 100, 100);
	if (res != ERRORCODE_OK)
	{
		goto ExitLine;
	}
ExitLine:
	if (res != ERRORCODE_OK)
	{
		m_socketClient.Disconnect();
	}
	return res;
}

ErrorCode PlcModbusTcp::Disconnect()
{
	return m_socketClient.Disconnect();
}

ErrorCode PlcModbusTcp::ReadRegister(int addr, int len, short* buf)
{
	EnterCriticalSection(&cs);
	ErrorCode res = ERRORCODE_OK;
	byte cmd[12];
	byte bufIn[1000];
	int cmdlen;
	if (!m_socketClient.IsConnected())
	{
		res=m_socketClient.Connect(m_ip, m_port, 100, 100);
		if (res != ERRORCODE_OK)
		{
			goto ExitLine;
		}
	}
	cmd[0] = m_cmdID/256;
	cmd[1] = m_cmdID%256;
	cmd[2] = 0x00;
	cmd[3] = 0x00;
	cmd[4] = 0x00;
	cmd[5] = 0x06;
	cmd[6] = 0x01;
	cmd[7] = 0x03;
	cmd[8] = addr / 256;
	cmd[9] = addr % 256;
	cmd[10] = len / 256;
	cmd[11] = len % 256;
	cmdlen = 12;
	res = m_socketClient.Write(cmd, cmdlen);
	if (res != ERRORCODE_OK)
	{
		goto ExitLine;
	}
	cmdlen = 1000;
	res = m_socketClient.Read(bufIn, cmdlen);
	if (res != ERRORCODE_OK)
	{
		goto ExitLine;
	}
	if (cmdlen !=9+2* len)
	{
		res = ERRORCODE_FAIL;
		goto ExitLine;
	}
	for (int i = 0; i < 8; i++)
	{
		if (i!=5&&bufIn[i] != cmd[i])
		{
			res = ERRORCODE_FAIL;
			goto ExitLine;
		}
	}
	for (int i = 0; i < len; i++)//响应从第10个字节开始为数据
	{
		buf[i] = bufIn[9 + 2 * i] * 256 + bufIn[9 + 2 * i + 1];//高位在前
	}
ExitLine:
	if (res != ERRORCODE_OK)
	{
		m_socketClient.Disconnect();
	}
	LeaveCriticalSection(&cs);
	return res;
}

ErrorCode PlcModbusTcp::WriteRegister(int addr, int len, short* buf)
{
	EnterCriticalSection(&cs);
	ErrorCode res = ERRORCODE_OK;
	byte cmd[1000];
	byte bufIn[100];
	int cmdlen;
	if (!m_socketClient.IsConnected())
	{
		res = m_socketClient.Connect(m_ip, m_port, 100, 100);
		if (res != ERRORCODE_OK)
		{
			goto ExitLine;
		}
	}
	m_cmdID++;
	cmd[0] = m_cmdID / 256;	//为此次通信事务处理标识符,一般每次通信之后将被要求加1以区别不同的通信数据报文;
	cmd[1] = m_cmdID % 256;
	cmd[2] = 0x00;			//协议标识符,00 00为modbus协议;
	cmd[3] = 0x00;
	cmd[4] = 0x00;			//数据长度,用来指示接下来数据的长度,单位字节;
	cmd[5] = 7+2*len;
	cmd[6] = 0x01;			//设备地址
							//用以标识连接在串行线或者网络上的远程服务端的地址。以上七个字节也被称为modbus报文头;
	cmd[7] = 0x10;			//功能码 03读 16写 保持寄存器数据
	cmd[8] = addr / 256;	//起始地址
	cmd[9] = addr % 256;
	cmd[10] = len / 256;	//请求寄存器数量 word数量
	cmd[11] = len % 256;
	cmd[12] = 2*len;	
	for (int i = 0; i < len; i++)
	{
		cmd[13 + i * 2] = (buf[i]>>8) & 0xFF;	//负数 右移为算术位移 左端补1 结果为255	(-100 short转byte为:11111111 10011100)
		cmd[13 + i * 2 +1] = buf[i] & 0xFF;
	}
	cmdlen = 13 + 2 * len;
	res = m_socketClient.Write(cmd, cmdlen);
	if (res != ERRORCODE_OK)
	{
		goto ExitLine;
	}
	cmdlen = 100;
	res = m_socketClient.Read(bufIn, cmdlen);
	if (res != ERRORCODE_OK)
	{
		goto ExitLine;
	}
	if (cmdlen != 12)
	{
		res = ERRORCODE_FAIL;
		goto ExitLine;
	}
	for (int i = 0; i < 12; i++)
	{
		if (i != 5 && bufIn[i] != cmd[i])
		{
			res = ERRORCODE_FAIL;
			goto ExitLine;
		}
	}
ExitLine:
	if (res != ERRORCODE_OK)
	{
		m_socketClient.Disconnect();
	}
	LeaveCriticalSection(&cs);
	return res;
}

 

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值