7 Commits

32 changed files with 1799 additions and 868 deletions
Split View
  1. +12
    -11
      Modbus_communication/Master_Salve_DLL/Master_Salve_DLL.vcxproj
  2. +10
    -17
      Modbus_communication/Master_Salve_DLL/Master_Salve_DLL.vcxproj.filters
  3. +51
    -0
      Modbus_communication/Master_Salve_DLL/Modbus.h
  4. +198
    -0
      Modbus_communication/Master_Salve_DLL/Modbus_Master.cpp
  5. +425
    -0
      Modbus_communication/Master_Salve_DLL/Modbus_Salve.cpp
  6. +7
    -0
      Modbus_communication/Master_Salve_DLL/Source.def
  7. +18
    -0
      Modbus_communication/Modbus_RTU_Salve/Modbus_TCP_log.txt
  8. +59
    -26
      Modbus_communication/Modbus_RTU_Salve/RTU_Salve.cpp
  9. +96
    -206
      Modbus_communication/Modbus_TCP/Interactive.cpp
  10. +16
    -15
      Modbus_communication/Modbus_TCP/Interactive.h
  11. +235
    -0
      Modbus_communication/Modbus_TCP/Modbus_Master.cpp
  12. +12
    -0
      Modbus_communication/Modbus_TCP/Modbus_Master.h
  13. +6
    -4
      Modbus_communication/Modbus_TCP/Modbus_TCP.vcxproj
  14. +10
    -4
      Modbus_communication/Modbus_TCP/Modbus_TCP.vcxproj.filters
  15. +143
    -250
      Modbus_communication/Modbus_TCP/TCP_client.cpp
  16. +14
    -4
      Modbus_communication/Modbus_TCP/TCP_client.h
  17. +1
    -1
      Modbus_communication/Modbus_TCP/main.h
  18. +10
    -10
      Modbus_communication/Modbus_communication.sln
  19. +0
    -106
      Modbus_communication/RTU_Salve_test/RTU_Test_Code.cpp
  20. +0
    -14
      Modbus_communication/RTU_Salve_test/RTU_Test_Code.h
  21. +0
    -9
      Modbus_communication/RTU_Salve_test/RTU_test.cpp
  22. +0
    -98
      Modbus_communication/TCP_Master_test/TCP_Test_Code.cpp
  23. +0
    -16
      Modbus_communication/TCP_Master_test/TCP_Test_Code.h
  24. +0
    -0
      Modbus_communication/UnitTest_DLL/TCP_Test.cpp
  25. +34
    -16
      Modbus_communication/UnitTest_DLL/UnitTest_DLL.vcxproj
  26. +3
    -15
      Modbus_communication/UnitTest_DLL/UnitTest_DLL.vcxproj.filters
  27. +217
    -0
      Modbus_communication/UnitTest_DLL/master_salve_test.cpp
  28. +20
    -0
      Modbus_communication/UnitTest_DLL/master_salve_test.h
  29. +30
    -0
      Modbus_communication/UnitTest_DLL/unittest1.cpp
  30. +0
    -0
      Modbus_communication/testini/1.ini
  31. +70
    -1
      Modbus_communication/testini/2.ini
  32. +102
    -45
      Modbus_communication/testini/3.ini

Modbus_communication/TCP_Master_test/TCP_Master_test.vcxproj → Modbus_communication/Master_Salve_DLL/Master_Salve_DLL.vcxproj View File

@@ -11,12 +11,12 @@
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{677F6F19-D890-4DE8-9EFD-08FE0E154AD0}</ProjectGuid>
<RootNamespace>TCP_Master_test</RootNamespace>
<ProjectGuid>{CB8E0444-CD69-430B-8ACF-8083D140A65F}</ProjectGuid>
<RootNamespace>Master_Salve_DLL</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
@@ -44,10 +44,11 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>DLLProvider;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ModuleDefinitionFile>Source.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -62,18 +63,18 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<ModuleDefinitionFile>Source.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\Modbus_TCP\common.cpp" />
<ClCompile Include="..\Modbus_TCP\TCP_client.cpp" />
<ClCompile Include="TCP_Test.cpp" />
<ClCompile Include="TCP_Test_Code.cpp" />
<ClInclude Include="Modbus.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Modbus_Master.cpp" />
<ClCompile Include="Modbus_Salve.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Modbus_TCP\common.h" />
<ClInclude Include="..\Modbus_TCP\TCP_client.h" />
<ClInclude Include="TCP_Test_Code.h" />
<None Include="Source.def" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

Modbus_communication/TCP_Master_test/TCP_Master_test.vcxproj.filters → Modbus_communication/Master_Salve_DLL/Master_Salve_DLL.vcxproj.filters View File

@@ -15,28 +15,21 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="TCP_Test.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="TCP_Test_Code.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="..\Modbus_TCP\common.cpp">
<ClInclude Include="Modbus.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Modbus_Master.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="..\Modbus_TCP\TCP_client.cpp">
<ClCompile Include="Modbus_Salve.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="TCP_Test_Code.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\Modbus_TCP\common.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\Modbus_TCP\TCP_client.h">
<Filter>头文件</Filter>
</ClInclude>
<None Include="Source.def">
<Filter>源文件</Filter>
</None>
</ItemGroup>
</Project>

+ 51
- 0
Modbus_communication/Master_Salve_DLL/Modbus.h View File

@@ -0,0 +1,51 @@
#ifndef __MODBUS_H
#define __MODBUS_H

#ifdef DLLProvider
#define DLL_EXPORT_IMPORT __declspec(dllexport)
#else
#define DLL_EXPORT_IMPORT __declspec(dllimport)
#endif

#include <stdio.h>
#include <winsock2.h>
#include <WS2tcpip.h>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <tchar.h>
#include <bitset>
#pragma comment(lib,"ws2_32.lib")
using namespace std;


#define DEVICE_ID 0x01 //É豸ID
#define Device_ID 0x09
#define MAX_Address 9999
#define MAX_NUMBER 300

enum Response_Type{
MSG_LEN_ERROR,
MABP_ERROR,
FUNCTION_CODE_ERROR,
START_ADDRESS_ERROR,
OPERATION_NUMBER_ERROR,
NORMAL_RESPONSE,
ABNORMAL_RESPONSE
};

enum Request_Type{
NO_RESPONSE,
NORMAL_REQUEST,
EXCEPTION_CODE_01,
EXCEPTION_CODE_03,
EXCEPTION_CODE_04,
};

DLL_EXPORT_IMPORT int Analysis_Response_Message(UINT8 *Response_Message, UINT8 *Request_Message, int response_message_len);
DLL_EXPORT_IMPORT int Create_TCP_Message(UINT8 *Message, int function_code, unsigned int operations_Number, unsigned int starting_address, string write_date);
DLL_EXPORT_IMPORT int Analysis_Response_Msg(UINT8 *Requst_Message, UINT8 *Response_Message, DWORD read_len);
DLL_EXPORT_IMPORT bool Create_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, int flage);
DLL_EXPORT_IMPORT void Init_Coil_Register(void);
#endif /* __MODBUS_H */

+ 198
- 0
Modbus_communication/Master_Salve_DLL/Modbus_Master.cpp View File

@@ -0,0 +1,198 @@
#include "Modbus.h"

UINT16 Transmission_Indicator = 0x00; //事务号

/*********************************************************************************************
* 功能    : 计算写入数据的字节数
* 描述   : 通过对应的功能码和操作数量计算对应的数据字节数
* 输入 : function_code 选择的功能码类型 operations_Number对应功能码类型的操作数量
* 输出 : Write_date_number 写入数据的字节数
*********************************************************************************************/
unsigned int Count_Write_date_number(int function_code, unsigned int operations_number)
{
unsigned int write_date_number = 0;
if (function_code == 0x01 || function_code == 0x03)
return write_date_number;
if (function_code == 0x0F) //读线圈
{
write_date_number = operations_number / 8;
if (operations_number % 8)
write_date_number++;
}
if (function_code == 0x10)
write_date_number = operations_number * 2;
return write_date_number;
}

/*********************************************************************************************
* 功能    : 计算请求报文计算预期响应报文字节数
* 描述   : 通过对应的功能码和操作数量计算对应的数据字节数
* 输入 : Function_code 选择的功能码类型 Operations_Number对应功能码类型的操作数量
* 输出 : Respone_len 预期响应的数据字节数
*********************************************************************************************/
unsigned int Count_Respone_Len(int function_code, unsigned int operations_number)
{
unsigned int respone_len = 0;
if (function_code == 0x0F || function_code == 0x10)
return respone_len;
if (function_code == 0x01) //读线圈
{
respone_len = operations_number / 8;
if (operations_number % 8)
respone_len++;
}
if (function_code == 0x03)
respone_len = operations_number * 2;
return respone_len;
}
/*********************************************************************************************
* 功能    : 检测响应报文长度
* 描述   : 对响应报文中存放长度字节进行判断和请求报文对比
* 输入 : Response_Message 响应报文 Request_Message 请求报文 Response_Message_len 接收到的数据长度
* 输出 : true 长度正常 false 长度异常
*********************************************************************************************/
bool Check_Response_Message_len(UINT8 *Response_Message, UINT8 *Request_Message, int response_message_len)
{
if ((response_message_len - 6) != Response_Message[5])
return false;
unsigned int operations_Number = Request_Message[10] << 8 | Request_Message[11];
unsigned int respone_Len = Count_Respone_Len(Request_Message[7], operations_Number);
if (Request_Message[7] == 0x0F || Request_Message[7] == 0x10)
if (response_message_len != 12)
return false;
if (Request_Message[7] == 0x01 || Request_Message[7] == 0x03)
{
if (respone_Len + 9 != response_message_len)
return false;
if (respone_Len != Response_Message[8])
return false;
}
return true;
}

/*********************************************************************************************
* 功能    : 判断响应报文是否可以正常解析
* 描述   : 通过长度和异常码等判定该响应报文是否可以解析
* 输入 : Response_Message 响应报文 Request_Message请求报文 Response_Message_len 响应报文长度
* 输出 : 响应数据类型
*********************************************************************************************/
int Analysis_Response_Message(UINT8 *Response_Message, UINT8 *Request_Message, int response_message_len)
{
if (response_message_len < 9 || response_message_len > 260)
return MSG_LEN_ERROR;
for (int i = 0; i < 7; i++)
{
if (i == 4 || i == 5) //后续字节长度
continue;
if (Response_Message[i] != Request_Message[i]) //0 1 传输标识,2 3 协议标识,6设备ID
return MABP_ERROR; //一旦不一致,判定为异常报文数据
}
if (Response_Message[4] != 0x00) //4 固定0x00
return MABP_ERROR;

if (Response_Message[7] == Request_Message[7] + 0x80)//先处理异常响应
{
if (response_message_len == 9)
{
return ABNORMAL_RESPONSE;
}
else
return MSG_LEN_ERROR;
}
if (Response_Message[7] != Request_Message[7]) //功能码判断
return FUNCTION_CODE_ERROR;
if (Request_Message[7] == 0x0F || Request_Message[7] == 0x10) //0F 10 地址和操作数量判定
{
for (int j = 8; j < 10; j++)
{
if (Request_Message[j] != Response_Message[j])
return START_ADDRESS_ERROR;
}
for (int j = 10; j < 12; j++)
{
if (Request_Message[j] != Response_Message[j])
return OPERATION_NUMBER_ERROR;
}
}
if (!Check_Response_Message_len(Response_Message, Request_Message, response_message_len))
return MSG_LEN_ERROR;
return NORMAL_RESPONSE;
}

/*********************************************************************************************
* 功能    : 生成MBAP报头
* 描述 : MBAP报文头的包括的内容:
* +-------------+---------+--------+--------+------------------------------+
* | 域 | 长度 | 客户机 | 服务器 | 描述 |
* +-------------+---------+--------+--------+------------------------------+
* |事务元标识符 | 2个字节 | 启动 | 复制 |请求/响应事务处理的识别码 |
* +-------------+---------+--------+--------+------------------------------+
* |协议标识符 | 2个字节 | 启动 | 复制 |0=MODBUS 协议 |
* +-------------+---------+--------+--------+------------------------------+
* | 长度 | 2个字节 | 启动 | 启动 |以下字节的数量 |
* +-------------+---------+--------+--------+------------------------------+
* |单元标识符 | 1个字节 | 启动 | 复制 |连接的远程从站的识别码 |
* 输入 : 无
* 输出 : MBAP报文头内容
*********************************************************************************************/
void Create_MBAP(UINT8 *Message, int function_code, unsigned int operations_number)
{
Message[0] = Transmission_Indicator >> 8;//事务号
Message[1] = (UINT8)Transmission_Indicator;
Transmission_Indicator++;
Message[2] = 0x00; //Modbus协议标识
Message[3] = 0x00;
Message[4] = 0x00;//后续字节长度
Message[5] = Count_Write_date_number(function_code, operations_number) + 0x06;
if (function_code == 0x0F || function_code == 0x10)//0f/10功能码后续字节数多1
{
Message[5] = Message[5] + 1;
}
Message[6] = DEVICE_ID;
}

/*********************************************************************************************
* 功能    : 字符串转UINT8类型
* 描述   : 根据写入数量和功能码类型输入相应的数据
* 输入 : *Message 消息帧存放的数组 Write_date 要转换的字符串
* Message_len消息帧数组的起始位置
* 输出 : Message_len 消息帧的长度
*********************************************************************************************/
int HexStringtoByte(UINT8 *Message, string write_date, int message_len, int function_code, unsigned int operations_Number)
{
if (write_date.length() == 0)
return message_len;
Message[message_len] = Count_Write_date_number(function_code, operations_Number);
message_len++;
const char *b = write_date.c_str();
int temp = 0;
for (unsigned int i = 0; i + 3 < write_date.length(); i = i + 3)
{
sscanf_s(b + i, "%02X", &temp);
Message[message_len] = (UINT8)temp;
message_len++;
}
sscanf_s(b + write_date.length() - 2, "%02X", &temp);
Message[message_len] = (UINT8)temp;
return ++message_len;
}

/*********************************************************************************************
* 功能    : 生成TCP模式下的消息帧
* 描述   : 根据要写入的数据生成消息帧
* 输入 : *Message 消息帧存放的数组 Write_date 写入数据的字符串
* Function_code 功能码 Operations_Number 操作数量 Starting_address起始地址
* 输出 : 消息帧的总长度
*********************************************************************************************/
int Create_TCP_Message(UINT8 *Message, int function_code, unsigned int operations_Number, unsigned int starting_address, string write_date)
{

Create_MBAP(Message, function_code, operations_Number);
Message[7] = function_code;//功能码
Message[8] = starting_address >> 8;//起始地址H
Message[9] = starting_address;//起始地址L
Message[10] = operations_Number >> 8;//操作数量H
Message[11] = operations_Number;//操作数量L
return HexStringtoByte(Message, write_date, 12, function_code, operations_Number);

}

+ 425
- 0
Modbus_communication/Master_Salve_DLL/Modbus_Salve.cpp View File

@@ -0,0 +1,425 @@
#include "Modbus.h"

bitset<MAX_Address> Coil_date; //0-9999
UINT16 Register[MAX_Address]; // 0-9999
unsigned int Response_Message_Len;
unsigned int RTU_Enable = 1;

/*********************************************************************************************
* 功能    : 计算写入数据的字节数
* 描述   : 通过对应的功能码和操作数量计算对应的数据字节数
* 输入 : Function_code 选择的功能码类型 Operations_Number对应功能码类型的操作数量
* 输出 : Read_date_number 写入数据的字节数
*********************************************************************************************/
unsigned int Count_Read_date_number(int function_code, unsigned int operations_number)
{
unsigned int read_date_number = 0;
if (function_code == 0x01 || function_code == 0x0F) //读线圈
{
read_date_number = operations_number / 8;
if (operations_number % 8)
read_date_number++;
}
if (function_code == 0x03 || function_code == 0x10)//读寄存器
read_date_number = operations_number * 2;
return read_date_number;
}


/*********************************************************************************************
* 功能     :  计算CRC校验
* 描述    : 获取Modbus—CRC-16的校验数据
* 输入 : *Data 计算校验数据 CRC_Len 数据长度
* 返回值 : Ret_CRC_date CRC校验结果
**********************************************************************************************/
UINT16 CRC_16(UINT8 *data, unsigned int crc_len)
{
UINT16 crc_date = 0XFFFF;//16位crc寄存器预置
UINT16 temp;
unsigned int i = 0, j = 0;
for (i = 0; i < crc_len; i++)
{
temp = *data & 0X00FF;//将八位数据与CRC寄存器亦或
data++;
crc_date ^= temp;
for (j = 0; j < 8; j++)
{
if (crc_date & 0X0001)//判断右移出的是不是1,如果是1则与多项式进行异或。
{
crc_date >>= 1;
crc_date ^= 0XA001;
}
else
{
crc_date >>= 1;
}
}
}
UINT16 ret_crc_date = crc_date >> 8;
ret_crc_date = ret_crc_date | crc_date << 8;
return ret_crc_date;
}
/*********************************************************************************************
* 功能     :  初始化线圈和寄存器
* 描述    : 对线圈和寄存器数组赋值为全1
* 输入 : 无
* 返回值 : 无
**********************************************************************************************/
void Init_Coil_Register(void)
{
for (int i = 0; i < MAX_Address; i++)
{
Coil_date[i] = 1;
Register[i] = 0xFFFF;
}
}
/*********************************************************************************************
* 功能     :  Bitset转UINT8类型
* 描述    : Bitset ==》UINT8
* 输入 : Bitset_Address Bitset的起始地址 Read_Number 要读取的位数
* 返回值 : Date 转换后的UNIT8数据
**********************************************************************************************/
UINT8 Bitset_to_Uint8(unsigned int bitset_address, unsigned int read_number)
{
UINT8 date = 0x00;

if (read_number >= 8)
{
unsigned int len = bitset_address + 7;
for (unsigned int i = 0; i < 8; i++)
{
date = date << 1;
date = date | (int)Coil_date[len--];
}
}
else
{
unsigned int len = bitset_address + read_number - 1;
for (unsigned int i = 0; i < read_number; i++)
{
date = date << 1;
date = date | (int)Coil_date[len--];
}
}
return date;
}

/*********************************************************************************************
* 功能     :  生成异常码响应报文
* 描述    : 对不支持的功能码生成对应的异常响应报文
* 输入 : *Requst_Message 请求报文 *Response_Message响应报文
* 返回值 : 无
**********************************************************************************************/
void Create_Abnormal_Code_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, UINT8 abnormal_code)
{
Response_Message[0] = Device_ID;
Response_Message[1] = Requst_Message[1] + 0x80;
Response_Message[2] = abnormal_code;
Response_Message_Len = 3;
UINT16 crc_date = CRC_16(Response_Message, 3);
Response_Message[3] = crc_date >> 8;//CRC_H
Response_Message[4] = (UINT8)crc_date; //CRC_L
Response_Message_Len = 5;
}

/*********************************************************************************************
* 功能     :  生成0x01功能码响应报文
* 描述    : 通过判断地址范围生成0x01对应的响应报文
* 输入 : *Requst_Message 请求报文 *Response_Message响应报文
* 返回值 : 无
**********************************************************************************************/
void Create_0x01_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message)
{
unsigned int start_Address = Requst_Message[2] << 8 | Requst_Message[3];
unsigned int address_range = start_Address + (Requst_Message[4] << 8 | Requst_Message[5]);
if (address_range < MAX_Address)//判断地址是否超限
{
unsigned int read_number = Requst_Message[4] << 8 | Requst_Message[5];//要读取的位数
unsigned int read_len = Count_Read_date_number(Requst_Message[1], read_number); //要读取的字节数
for (unsigned int i = 3; i < read_len + 3; i++)
{
Response_Message[i] = Bitset_to_Uint8(start_Address, read_number);
start_Address += 8;
read_number -= 8;
}
Response_Message[0] = Device_ID;
Response_Message[1] = Requst_Message[1];
Response_Message[2] = read_len; //响应报文中的后续字节数
UINT16 crc_date = CRC_16(Response_Message, read_len + 3);
Response_Message_Len = read_len + 2 + 3;
Response_Message[Response_Message_Len - 2] = crc_date >> 8;//CRC_H
Response_Message[Response_Message_Len - 1] = (UINT8)crc_date; //CRC_L
}
else
{
Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x02);
}
}

/*********************************************************************************************
* 功能     :  生成0x03功能码响应报文
* 描述    : 通过判断地址范围生成0x03对应的响应报文
* 输入 : *Requst_Message 请求报文 *Response_Message响应报文
* 返回值 : 无
**********************************************************************************************/
void Create_0x03_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message)
{
unsigned int start_Address = Requst_Message[2] << 8 | Requst_Message[3];
unsigned int address_range = start_Address + (Requst_Message[4] << 8 | Requst_Message[5]);
if (address_range < MAX_Address) //判断地址是否超限
{
unsigned int read_number = Requst_Message[4] << 8 | Requst_Message[5];//要读取的寄存器数量
unsigned int read_len = Count_Read_date_number(Requst_Message[1], read_number); //要读取的字节数
for (unsigned int i = 3; i < read_len + 3; i = i + 2)
{
Response_Message[i] = Register[start_Address] >> 8;
Response_Message[i + 1] = (UINT8)Register[start_Address];
start_Address += 1;
}
Response_Message[0] = Device_ID;
Response_Message[1] = Requst_Message[1];
Response_Message[2] = read_len; //响应报文中的后续字节数
UINT16 crc_date = CRC_16(Response_Message, read_len + 3);
Response_Message_Len = read_len + 2 + 3;
Response_Message[Response_Message_Len - 2] = crc_date >> 8;//CRC_H
Response_Message[Response_Message_Len - 1] = (UINT8)crc_date; //CRC_L
}
else //地址超限
{
Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x02);
}
}

/*********************************************************************************************
* 功能     :  写入线圈
* 描述    : 将数据写入线圈中
* 输入 : Write_date_Message 要写入的数据 Write_Number要写入的位数 Start_Address起始地址
* 返回值 : 无
**********************************************************************************************/
void Write_Coil_date(UINT8 write_date_message, unsigned int write_number, unsigned int start_address)
{
if (write_number >= 8)
{
for (unsigned int i = start_address; i < start_address + 8; i++)
{
Coil_date[i] = write_date_message & 1;
write_date_message = write_date_message >> 1;
}
}
else
{
for (unsigned int i = start_address; i < start_address + write_number; i++)
{
Coil_date[i] = write_date_message & 1;
write_date_message = write_date_message >> 1;
}
}
}

/*********************************************************************************************
* 功能     :  生成0x0F功能码响应报文
* 描述    : 通过判断地址范围生成0x0F对应的响应报文
* 输入 : *Requst_Message 请求报文 *Response_Message响应报文
* 返回值 : 无
**********************************************************************************************/
void Create_0x0F_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message)
{
unsigned int start_Address = Requst_Message[2] << 8 | Requst_Message[3];
unsigned int address_range = start_Address + (Requst_Message[4] << 8 | Requst_Message[5]);
if (address_range < MAX_Address)//判断地址是否超限
{
unsigned int write_Number = Requst_Message[4] << 8 | Requst_Message[5];//要写入的位数
for (int i = 7; i < Requst_Message[6] + 7; i++)//执行写入线圈操作
{
Write_Coil_date(Requst_Message[i], write_Number, start_Address);
write_Number -= 8;
start_Address += 8;
}
Response_Message[0] = Device_ID;
Response_Message[1] = Requst_Message[1];
Response_Message[2] = Requst_Message[2];
Response_Message[3] = Requst_Message[3];
Response_Message[4] = Requst_Message[4];
Response_Message[5] = Requst_Message[5];
UINT16 crc_date = CRC_16(Response_Message, 6);
Response_Message[6] = crc_date >> 8;//CRC_H
Response_Message[7] = (UINT8)crc_date; //CRC_L
Response_Message_Len = 8;
}
else //地址超限
{
Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x02);
}
}

/*********************************************************************************************
* 功能     :  生成0x10功能码响应报文
* 描述    : 通过判断地址范围生成0x10对应的响应报文
* 输入 : *Requst_Message 请求报文 *Response_Message响应报文
* 返回值 : 无
**********************************************************************************************/
void Create_0x10_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message)
{
unsigned int start_Address = Requst_Message[2] << 8 | Requst_Message[3];
unsigned int address_range = start_Address + (Requst_Message[4] << 8 | Requst_Message[5]);
if (address_range < MAX_Address)//判断地址是否超限
{
for (int i = 7; i < Requst_Message[6] + 7; i = i + 2)//执行写入寄存器操作
{
Register[start_Address] = Requst_Message[i] << 8 | Requst_Message[i + 1];
start_Address++;
}
Response_Message[0] = Device_ID;
Response_Message[1] = Requst_Message[1];
Response_Message[2] = Requst_Message[2];
Response_Message[3] = Requst_Message[3];
Response_Message[4] = Requst_Message[4];
Response_Message[5] = Requst_Message[5];
UINT16 crc_date = CRC_16(Response_Message, 6);
Response_Message[6] = crc_date >> 8;//CRC_H
Response_Message[7] = (UINT8)crc_date; //CRC_L
Response_Message_Len = 8;
}
else //地址超限
{
Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x02);
}
}


/*********************************************************************************************
* 功能     :  CRC校验
* 描述    : 对请求报文中的数据进行CRC校验
* 输入 : *Requst_Message 请求报文 Read_len 接收到到的字节数
* 返回值 : true CRC校验通过
* false CRC校验不通过
**********************************************************************************************/
bool Check_Requst_Message_CRC(UINT8 *Requst_Message, DWORD read_len)
{
UINT16 crc_data = CRC_16(Requst_Message, read_len - 2);
UINT16 message_crc = Requst_Message[read_len - 2] << 8 | Requst_Message[read_len - 1];
if (crc_data != message_crc)
return false;
return true;
}

/*********************************************************************************************
* 功能     :  异常码03判定--请求报文长度校验
* 描述    : 对请求报文的字节长度进行计算校验
* 输入 : *Requst_Message 请求报文 Read_len 接收到到的字节数
* 返回值 : true 长度校验通过
* false 长度校验不通过
**********************************************************************************************/
bool Check_Requst_Message_Len(UINT8 *Requst_Message, DWORD read_len)
{
if (Requst_Message[1] == 0x01 || Requst_Message[1] == 0x03)
{
if (read_len != 8)
return false;
}
if (Requst_Message[1] == 0x0F || Requst_Message[1] == 0x10)
{
unsigned int number = Requst_Message[4] << 8 | Requst_Message[5];
unsigned int count_len = Count_Read_date_number(Requst_Message[1], number);
if (Requst_Message[6] != count_len || read_len != count_len + 9)
return false;
}
return true;
}

/*********************************************************************************************
* 功能     :  异常码03判定--请求报文中的操作数量判定
* 描述    : 对请求报文中的操作数量进行判定
* 输入 : *Requst_Message 请求报文 Read_len 接收到到的字节数
* 返回值 : true 校验通过
* false 校验不通过
**********************************************************************************************/
bool Check_Operation_Number_Requst_Message(UINT8 *Requst_Message)
{
unsigned int operation_number = Requst_Message[4] << 8 | Requst_Message[5];
if (Requst_Message[1] == 0x01)
{
if (operation_number == 0 || operation_number > 2000)
return false;
}
if (Requst_Message[1] == 0x03)
{
if (operation_number == 0 || operation_number > 125)
return false;
}
if (Requst_Message[1] == 0x0F)
{
if (operation_number < 1 || operation_number > 1968)
return false;
}
if (Requst_Message[1] == 0x10)
{
if (operation_number < 1 || operation_number > 123)
return false;
}
return true;
}

/*********************************************************************************************
* 功能     :  解析请求报文
* 描述    : 判断该请求报文的返回类型
* 输入 : *Requst_Message 请求报文 *Response_Message 响应报文 Read_len 接收到到的字节数
* 返回值 : 响应类型
**********************************************************************************************/
int Analysis_Response_Msg(UINT8 *Requst_Message, UINT8 *Response_Message, DWORD read_len)
{
if (read_len < 8)
return NO_RESPONSE;
if (!Check_Requst_Message_CRC(Requst_Message, read_len))//CRC校验报文是否正确
return NO_RESPONSE;
if (Requst_Message[0] != Device_ID) //检查设备ID一致
return NO_RESPONSE;
if (RTU_Enable == 0)
{
return EXCEPTION_CODE_04;
}
if (!Check_Requst_Message_Len(Requst_Message, read_len) || !Check_Operation_Number_Requst_Message(Requst_Message))//检查请求报文长度是否正确
{
return EXCEPTION_CODE_03;
}
if (Requst_Message[1] != 0x01 && Requst_Message[1] != 0x03 && Requst_Message[1] != 0x0F && Requst_Message[1] != 0x10)
return EXCEPTION_CODE_01;
return NORMAL_REQUEST;
}

/*********************************************************************************************
* 功能     :  生成正常读写响应报文和02异常码响应
* 描述    : 通过对功能码进行判断,进行相应的读写操作后,生成对应的相应报文
* 输入 : *Requst_Message 请求报文 *Response_Message 响应报文
* 返回值 : 无
**********************************************************************************************/
void Create_Normal_Message(UINT8 *Requst_Message, UINT8 *Response_Message)
{
switch (Requst_Message[1])
{
case 0x01:Create_0x01_Response_Message(Requst_Message, Response_Message); break;
case 0x03:Create_0x03_Response_Message(Requst_Message, Response_Message); break;
case 0x0F:Create_0x0F_Response_Message(Requst_Message, Response_Message); break;
case 0x10:Create_0x10_Response_Message(Requst_Message, Response_Message); break;
default: Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x04);
}
}
/*********************************************************************************************
* 功能     :  生成响应报文
* 描述    : 检查设备请求报文来生成对应功能的响应报文
* 输入 : *Requst_Message 请求报文 *Response_Message响应报文
* 返回值 : true 生成响应报文
* false 不生成响应报文
**********************************************************************************************/
bool Create_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, int flage)
{
switch (flage)
{
case NO_RESPONSE:return false;
case NORMAL_REQUEST: Create_Normal_Message(Requst_Message, Response_Message); break;
case EXCEPTION_CODE_01:Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x01); break;
case EXCEPTION_CODE_03:Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x03); break;
case EXCEPTION_CODE_04:Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x04); break;
}
return true;
}

+ 7
- 0
Modbus_communication/Master_Salve_DLL/Source.def View File

@@ -0,0 +1,7 @@
LIBRARY Master_Salve_Dll
EXPORTS
Analysis_Response_Message @1
Create_TCP_Message @2
Analysis_Response_Msg @3
Create_Response_Message @4
Init_Coil_Register @5

+ 18
- 0
Modbus_communication/Modbus_RTU_Salve/Modbus_TCP_log.txt View File

@@ -438,3 +438,21 @@
2020-9-16 19:3:34 Recv:09 03 02 00 00 59 85
2020-9-16 19:3:35 Send:09 03 00 00 00 01 85 42
2020-9-16 19:3:35 Recv:09 03 02 00 00 59 85
2020-9-18 18:42:31 Send:09 01 01 00 00 00 01 7F D1
2020-9-18 18:42:31 Recv:09 81 03 81 93
2020-9-18 18:42:33 Send:09 01 01 00 00 00 01 7F D1
2020-9-18 18:42:33 Recv:09 81 03 81 93
2020-9-18 18:42:40 Send:09 01 01 00 00 00 01 7F D1
2020-9-18 18:42:40 Recv:09 81 03 81 93
2020-9-18 18:42:41 Send:09 01 01 00 00 00 01 7F D1
2020-9-18 18:42:41 Recv:09 81 03 81 93
2020-9-18 18:42:46 Send:09 01 01 00 00 00 01 7F D1
2020-9-18 18:42:46 Recv:09 81 03 81 93
2020-9-18 18:43:7 Send:09 01 00 00 00 01 FC 82
2020-9-18 18:43:7 Recv:09 01 01 01 92 28
2020-9-18 18:43:8 Send:09 01 00 00 00 01 FC 82
2020-9-18 18:43:8 Recv:09 01 01 01 92 28
2020-9-18 18:43:11 Send:09 01 00 00 00 01 FC 82
2020-9-18 18:43:11 Recv:09 01 01 01 92 28
2020-9-18 18:43:11 Send:09 01 00 00 00 01 FC 82
2020-9-18 18:43:11 Recv:09 01 01 01 92 28

+ 59
- 26
Modbus_communication/Modbus_RTU_Salve/RTU_Salve.cpp View File

@@ -7,6 +7,13 @@ UINT16 Register[MAX_Address]; // 0-9999
unsigned int Response_Message_Len;
unsigned int RTU_Enable = 1;

enum Request_type{
NO_RESPONSE,
NORMAL_RESPONSE,
EXCEPTION_CODE_01,
EXCEPTION_CODE_03,
EXCEPTION_CODE_04,
};
/*********************************************************************************************
* 功能     :  初始化线圈和寄存器
* 描述    : 对线圈和寄存器数组赋值为全1
@@ -307,38 +314,67 @@ bool Check_Operation_Number_Requst_Message(UINT8 *Requst_Message)
}
return true;
}

/*********************************************************************************************
* 功能     :  生成响应报文
* 描述    : 检查设备请求报文来生成对应功能的响应报文
* 输入 : *Requst_Message 请求报文 *Response_Message响应报文
* 返回值 : true 生成响应报文
* false 不生成响应报文
* 功能     :  解析请求报文
* 描述    : 判断该请求报文的返回类型
* 输入 : *Requst_Message 请求报文 *Response_Message 响应报文 Read_len 接收到到的字节数
* 返回值 : 响应类型
**********************************************************************************************/
bool Create_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, DWORD read_len)
int Analysis_Response_Msg(UINT8 *Requst_Message, UINT8 *Response_Message, DWORD read_len)
{
if (Requst_Message[0] != Device_ID) //检查设备ID一致
return false;
if (read_len < 8 || read_len > 256)
return false;
return NO_RESPONSE;
if (!Check_Requst_Message_CRC(Requst_Message, read_len))//CRC校验报文是否正确
return false;
return NO_RESPONSE;
if (Requst_Message[0] != Device_ID) //检查设备ID一致
return NO_RESPONSE;
if (RTU_Enable == 0)
{
Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x04);
return true;
return EXCEPTION_CODE_04;
}
if (!Check_Requst_Message_Len(Requst_Message, read_len) || !Check_Operation_Number_Requst_Message(Requst_Message))//检查请求报文长度是否正确
{
Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x03);
return true;
return EXCEPTION_CODE_03;
}
if (Requst_Message[1] != 0x01 && Requst_Message[1] != 0x03 && Requst_Message[1] != 0x0F && Requst_Message[1] != 0x10)
return EXCEPTION_CODE_01;
return NORMAL_RESPONSE;
}

/*********************************************************************************************
* 功能     :  生成正常读写响应报文和02异常码响应
* 描述    : 通过对功能码进行判断,进行相应的读写操作后,生成对应的相应报文
* 输入 : *Requst_Message 请求报文 *Response_Message 响应报文
* 返回值 : 无
**********************************************************************************************/
void Create_Normal_Message(UINT8 *Requst_Message, UINT8 *Response_Message)
{
switch (Requst_Message[1])
{
case 0x01:Create_0x01_Response_Message(Requst_Message, Response_Message); break;
case 0x03:Create_0x03_Response_Message(Requst_Message, Response_Message); break;
case 0x0F:Create_0x0F_Response_Message(Requst_Message, Response_Message); break;
case 0x10:Create_0x10_Response_Message(Requst_Message, Response_Message); break;
default: Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message,0x01);
default: Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x04);
}
}
/*********************************************************************************************
* 功能     :  生成响应报文
* 描述    : 检查设备请求报文来生成对应功能的响应报文
* 输入 : *Requst_Message 请求报文 *Response_Message响应报文
* 返回值 : true 生成响应报文
* false 不生成响应报文
**********************************************************************************************/
bool Create_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, int flage)
{
switch (flage)
{
case NO_RESPONSE:return false;
case NORMAL_RESPONSE: Create_Normal_Message(Requst_Message, Response_Message); break;
case EXCEPTION_CODE_01:Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x01); break;
case EXCEPTION_CODE_03:Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x03); break;
case EXCEPTION_CODE_04:Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x04); break;
}
return true;
}
@@ -360,19 +396,16 @@ int Modbus_RTU_Salve(void)
}
if (requst_message_len == 0)
continue;//长度为0 重新连接了

if (Create_Response_Message(Requst_Message, Response_Message, requst_message_len))//解析
int flage = Analysis_Response_Msg(Requst_Message, Response_Message, requst_message_len);//解析请求报文
if (!Create_Response_Message(Requst_Message, Response_Message, flage))//生成
continue;//无响应
if(!SendData(Handle_Com, (char*)Response_Message, Response_Message_Len))//发送
{
if(!SendData(Handle_Com, (char*)Response_Message, Response_Message_Len))//发送
{
printf("发送响应报文失败\n");
continue;
}
Printf_Message(Requst_Message, 1, requst_message_len);
Printf_Message(Response_Message, 0, Response_Message_Len);
printf("发送响应报文失败\n");
continue;
}
else
continue;//无响应
Printf_Message(Requst_Message, 1, requst_message_len);
Printf_Message(Response_Message, 0, Response_Message_Len);
}
CloseHandle(Handle_Com);
getchar();


Modbus_communication/Modbus_TCP/common.cpp → Modbus_communication/Modbus_TCP/Interactive.cpp View File

@@ -1,66 +1,6 @@
#include "common.h"
#include "Interactive.h"


/*********************************************************************************************
* 功能    : IP地址有效性检测
* 描述   : 检测输入的IP地址是否合法
* 输入 : IP 输入的IP地址
* 输出 : true IP地址合法
* false IP地址非法
*********************************************************************************************/
bool Check_IP(string ip)
{
int s[4];
if (ip.length() < 7 || ip.length() > 15) //长度判定
return false;
if (sscanf_s(ip.c_str(), "%d.%d.%d.%d", &s[0], &s[1], &s[2], &s[3]) != 4) //IPV4格式正确
{
return false;
}
string newip = to_string(s[0]) + "." + to_string(s[1]) + "." + to_string(s[2]) + "." + to_string(s[3]);
if (ip != newip) //前导0
return false;
if ((s[0] & 0xffffff00) || (s[1] & 0xffffff00) || (s[2] & 0xffffff00) || (s[3] & 0xffffff00)) //判断每一段大小是否符合要求
{
return false;
}
return true;
}

/*********************************************************************************************
* 功能    : 获取从站IP地址和端口号
* 描述   : 终端输入从站IP地址和端口号
* 输入 : IP 地址 (IPV4)
* *Port_number 端口号(1-65535)
* 输出 : 无
*********************************************************************************************/
void Input_IP(string& ip, unsigned int *port_number)
{
int i = 1;
do
{
if (i == 1)
{
cout << "请输入从站IP:";
i = 0;
}
else
cout << "IP地址格式不正确,请重新输入从站IP:";
cin >> ip;
} while (!Check_IP(ip));

i = 1;
cout << "IP地址输格式入正确,请输入从站端口号:";
do
{
if (i != 1)
cout << "请重新输入从站端口号:";
cin >> *port_number;
i = 0;
} while (*port_number == 0 || *port_number > 65535); //端口不能为0 ,端口号范围1---65535

}

/*********************************************************************************************
* 功能    : 选择功能码
* 描述   : 在功能码 0x01 0x03 0x0F 0x10中选择一个功能码
@@ -218,33 +158,12 @@ unsigned int Count_Write_date_number(int function_code, unsigned int operations_
return write_date_number;
}

/*********************************************************************************************
* 功能    : 计算请求报文计算预期响应报文字节数
* 描述   : 通过对应的功能码和操作数量计算对应的数据字节数
* 输入 : Function_code 选择的功能码类型 Operations_Number对应功能码类型的操作数量
* 输出 : Respone_len 预期响应的数据字节数
*********************************************************************************************/
unsigned int Count_Respone_Len(int function_code, unsigned int operations_number)
{
unsigned int respone_len = 0;
if (function_code == 0x0F || function_code == 0x10)
return respone_len;
if (function_code == 0x01) //读线圈
{
respone_len = operations_number / 8;
if (operations_number % 8)
respone_len++;
}
if (function_code == 0x03)
respone_len = operations_number * 2;
return respone_len;
}

/*********************************************************************************************
* 功能    : 输入写入数据
* 描述   : 根据写入数量和功能码类型输入相应的数据
* 输入 : Function_code 选择的功能码类型 Operations_Number对应功能码类型的操作数量
* 输出 : Write_date 写入的数据
* 输出 : Write_date 写入的数据
*********************************************************************************************/
string Input_Write_date(int function_code, unsigned int operations_Number)
{
@@ -253,7 +172,7 @@ string Input_Write_date(int function_code, unsigned int operations_Number)
unsigned int write_date_number = Count_Write_date_number(function_code, operations_Number);
if (function_code == 0x01 || function_code == 0x03)
return write_date;//读线圈/寄存器不需要输入写入数据
printf("请输入N组写入数据(2位16进制为一组,空格间隔)例如:00 00 01 00 20 05\n");
do
{
@@ -272,6 +191,67 @@ string Input_Write_date(int function_code, unsigned int operations_Number)
return write_date;
}


/*********************************************************************************************
* 功能    : 打印读取从站的线圈状态
* 描述   : 对响应报文中的数据进行解析和显示
* 输入 : Response_Message 响应报文 Request_Message 请求报文
* 输出 : 无
*********************************************************************************************/
void Printf_Coil_date(UINT8 *Response_Message, UINT8 *Request_Message)
{
printf("从站设备ID %02X 功能码为 %02X\n", Response_Message[6], Response_Message[7]);
unsigned int temp1 = ((Request_Message[8] << 8) | Request_Message[9]);
unsigned int number = ((Request_Message[10] << 8) | Request_Message[11]);
printf("线圈起始地址为%d \n", temp1);
unsigned int temp = temp1;
for (int i = 0; i < Response_Message[8]; i++)
{
unsigned int temp2 = temp + 7;
if (temp2 > temp1 + number - 1)
temp2 = temp1 + number - 1;
printf("线圈%d --- %d的状态为:%02X \n", temp2, temp, Response_Message[9 + i]);
temp = temp + 8;
}
}

/*********************************************************************************************
* 功能    : 打印读取从站的寄存器状态
* 描述   : 对响应报文中的数据进行解析和显示
* 输入 : Response_Message 响应报文 Request_Message 请求报文
* 输出 : 无
*********************************************************************************************/
void Printf_Register_date(UINT8 *Response_Message, UINT8 *Request_Message)
{
printf("从站设备ID %02X 功能码为 %02X\n", Response_Message[6], Response_Message[7]);
unsigned int temp1 = ((Request_Message[8] << 8) | Request_Message[9]);
printf("寄存器起始地址为%d \n", temp1);
for (int i = 0; i < Response_Message[8]; i = i + 2)
{
printf("寄存器%d的值为:%02X %02X \n", temp1++, Response_Message[9 + i], Response_Message[10 + i]);
}
}

/*********************************************************************************************
* 功能    : 打印读取异常响应报文信息
* 描述   : 对响应报文中的数据进行解析和显示
* 输入 : Response_Message 响应报文
* 输出 : 无
*********************************************************************************************/
void Printf_Anomaly_date(UINT8 *Response_Message)
{
UINT8 anomaly_code = Response_Message[8];
printf("从站设备ID %02X 功能码为 %02X\n", Response_Message[6], Response_Message[7]);
switch (anomaly_code)
{
case 0x01: printf("%02X : 从站设备不支持此功能码\n", anomaly_code); break;
case 0x02: printf("%02X : 指定的数据地址在从站设备中不存在\n", anomaly_code); break;
case 0x03: printf("%02X : 指定的数据超过范围或者不允许使用\n", anomaly_code); break;
case 0x04: printf("%02X : 从站设备处理响应的过程中,出现未知错误等\n", anomaly_code); break;
default: printf("Unkown Other Error!!!!!\n");
}
}

/*********************************************************************************************
* 功能    : 日志记录
* 描述   : 记录每次通信的请求和响应报文
@@ -288,14 +268,14 @@ void Log_Note(UINT8 *Message, int flage, int message_len)
p = gmtime(&timep);
string recv_str = to_string(1900 + p->tm_year) + "-" + to_string(1 + p->tm_mon) + "-" + to_string(p->tm_mday)
+ " " + to_string(8 + p->tm_hour) + ":" + to_string(p->tm_min) + ":" + to_string(p->tm_sec) + " Recv:";
string send_str= to_string(1900 + p->tm_year) + "-" + to_string(1 + p->tm_mon) + "-" + to_string(p->tm_mday)
string send_str = to_string(1900 + p->tm_year) + "-" + to_string(1 + p->tm_mon) + "-" + to_string(p->tm_mday)
+ " " + to_string(8 + p->tm_hour) + ":" + to_string(p->tm_min) + ":" + to_string(p->tm_sec) + " Send:";

/* 打开文件用于读写 */
if ((fp = fopen("Modbus_TCP_log.txt", "a+")) == NULL)
{
printf("打开文件失败");
return ;
return;
}
if (flage == 1)
{
@@ -304,7 +284,7 @@ void Log_Note(UINT8 *Message, int flage, int message_len)
{
fprintf(fp, "%02X ", Message[i]);
}
fprintf(fp,"\n");
fprintf(fp, "\n");
}
else
{
@@ -319,136 +299,46 @@ void Log_Note(UINT8 *Message, int flage, int message_len)
fp = NULL;
}

/*********************************************************************************************
* 功能    : socket版本
* 描述   : 启动socket服务
* 输入 : 无
* 输出 : true 启动成功
* false 启动失败
*********************************************************************************************/
bool InitSocket_Version(void)
{
WORD sockVersion = MAKEWORD(2, 2);//使用winsocket2.2版本
WSADATA wsaData;
if (WSAStartup(sockVersion, &wsaData) != 0)
{
return false;
}
return true;
}

/*********************************************************************************************
* 功能    : 初始化客户端
* 描述   : 根据终端输入从站IP地址和端口号连接对应的服务器,设置超时时间
* 输入 : 无
* 输出 : ClientSocket 连接成功的套接字
*********************************************************************************************/
SOCKET Init_Client(void)
void Printf_Message(UINT8 *Message, int flage, int message_len)
{
if (InitSocket_Version() == 0)
{
printf("启动Socket服务失败,请检查Socket版本");
return INVALID_SOCKET;
}
string ip_address;
unsigned int port_number;
Input_IP(ip_address, &port_number);
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in serversock_in;
serversock_in.sin_addr.S_un.S_addr = inet_addr(ip_address.c_str());
serversock_in.sin_family = AF_INET;
serversock_in.sin_port = htons(port_number);
if (SOCKET_ERROR == connect(clientSocket, (SOCKADDR*)&serversock_in, sizeof(SOCKADDR)))
if (flage == 1)
printf("主站请求 :");
else
printf("从站响应 :");
for (int i = 0; i < message_len; i++)
{
cout << "尝试连接TCP从站失败" << endl;
return INVALID_SOCKET;
printf("%02x ", Message[i]);
}
cout << "连接TCP从站成功" << endl;
TIMEVAL timeout;
timeout.tv_sec = 200; //ms
timeout.tv_usec = 0; //us
setsockopt(clientSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));//设置接收超时时间
return clientSocket;
}

void Clear_buf(SOCKET clientSocket)
{
unsigned long bytesToRecv;
char temp[500];
do
{
ioctlsocket(clientSocket, FIONREAD, &bytesToRecv);
if (bytesToRecv != 0)//不等于0时进行清理操作
{
if (bytesToRecv > 500)
{
recv(clientSocket, temp, 500, 0);
}
else
recv(clientSocket, temp, bytesToRecv, 0);
}
} while (bytesToRecv != 0);

printf("\n");
if (LOG_NOTE_SWITCH)
Log_Note(Message, flage, message_len);
}

bool Send_date(SOCKET clientSocket, UINT8 *Request_Message, int request_message_len)
void Printf_Analysis_Outcome(UINT8 *Response_Message, UINT8 *Request_Message)
{
Clear_buf(clientSocket); //清理缓冲区
int status = send(clientSocket, (char*)Request_Message, request_message_len, 0);
if (status == (-1))
switch (Response_Message[7])
{
return false;
case 0x01:Printf_Coil_date(Response_Message, Request_Message); break;
case 0x03:Printf_Register_date(Response_Message, Request_Message); break;
case 0x0F:printf("成功写入从站线圈%d个\n", ((Request_Message[10] << 8) | Request_Message[11])); break;
case 0x10:printf("成功写入从站寄存器%d个\n", ((Request_Message[10] << 8) | Request_Message[11])); break;
default: printf("Other Error");
}
return true;
}

bool Abnormal_Connection(SOCKET *clientSocket)
{
printf("连接异常,请检查连接状态。\n");
printf("**************************** Press Enter To Contioun ****************************\n");
getchar();
system("cls");
closesocket(*clientSocket);
WSACleanup();
printf("是否重新连接服务器: 1 重新连接 0 关闭本软件\n");
int flage = 0;
do
{
cin >> flage;
cin.clear();
cin.sync();
} while (!(flage == 0 || flage == 1));
if (flage == 0)
return false;
system("cls");
do
{
*clientSocket = Init_Client();
} while (INVALID_SOCKET == *clientSocket);
system("cls");
return true;
}

int Recv_date(SOCKET clientSocket, UINT8 *Response_Message)
void Printf_Interactive_Data(UINT8 *Response_Message, UINT8 *Request_Message, int flage, int request_message_len, int response_message_len)
{
int Response_Message_len = recv(clientSocket, (char*)Response_Message, 600, 0);
if (Response_Message_len > 0)
Printf_Message(Request_Message, 1, request_message_len);
Printf_Message(Response_Message, 0, response_message_len);
switch (flage)
{
return Response_Message_len;
case MSG_LEN_ERROR: printf("Message Length Error"); break;
case MABP_ERROR:printf("MBAP Date Error"); break;
case FUNCTION_CODE_ERROR:printf("Function Code Error"); break;
case START_ADDRESS_ERROR:printf("Start Address Error"); break;
case OPERATION_NUMBER_ERROR:printf("Operation Number Error"); break;
case NORMAL_RESPONSE: Printf_Analysis_Outcome(Response_Message, Request_Message); break;
case ABNORMAL_RESPONSE:Printf_Anomaly_date(Response_Message); break;
default:printf("Other Error");
}
return 0;
}

bool Test_Connection_status(SOCKET clientSocket)
{
TIMEVAL timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
fd_set reads;
FD_ZERO(&reads);
FD_SET(clientSocket, &reads);
if (select(0, &reads, 0, 0, &timeout))
return false;
else
return true;
}

Modbus_communication/Modbus_TCP/common.h → Modbus_communication/Modbus_TCP/Interactive.h View File

@@ -1,20 +1,27 @@
#ifndef __COMMON_H
#define __COMMON_H
#ifndef __INTERACTIVE_H
#define __INTERACTIVE_H


#include <stdio.h>
#include <winsock2.h>
#include <WS2tcpip.h>
#include <Windows.h>
#include <vector>
#include <string>
#include <iostream>
#include <time.h>
#pragma comment(lib,"ws2_32.lib")
#include <iostream>
using namespace std;

#define DEVICE_ID 0x01 //设备ID
#define LOG_NOTE_SWITCH 1 //日志记录控制位

#define LOG_NOTE_SWITCH 1 //日志记录控制位

enum Response_Type{
MSG_LEN_ERROR,
MABP_ERROR,
FUNCTION_CODE_ERROR,
START_ADDRESS_ERROR,
OPERATION_NUMBER_ERROR,
NORMAL_RESPONSE,
ABNORMAL_RESPONSE
};

int Input_Function_code(void);
unsigned int Input_Starting_address(void);
@@ -22,13 +29,7 @@ unsigned int Input_Operations_number(int function_code);
unsigned int Count_Write_date_number(int function_code, unsigned int operations_Number);
string Input_Write_date(int function_code, unsigned int operations_Number);
void Log_Note(UINT8 *Message, int flage, int message_len);

unsigned int Count_Respone_Len(int function_code, unsigned int operations_number);
SOCKET Init_Client(void);
bool Send_date(SOCKET clientSocket, UINT8 *Request_Message, int request_message_len);
bool Abnormal_Connection(SOCKET *clientSocket);
int Recv_date(SOCKET clientSocket, UINT8 *Response_Message);
bool Test_Connection_status(SOCKET clientSocket);
void Printf_Interactive_Data(UINT8 *Response_Message, UINT8 *Request_Message, int flage, int request_message_len, int response_message_len);


#endif

+ 235
- 0
Modbus_communication/Modbus_TCP/Modbus_Master.cpp View File

@@ -0,0 +1,235 @@
#include "Modbus_Master.h"
UINT16 Transmission_Indicator = 0x00; //事务号

/*********************************************************************************************
* 功能    : 计算请求报文计算预期响应报文字节数
* 描述   : 通过对应的功能码和操作数量计算对应的数据字节数
* 输入 : Function_code 选择的功能码类型 Operations_Number对应功能码类型的操作数量
* 输出 : Respone_len 预期响应的数据字节数
*********************************************************************************************/
unsigned int Count_Respone_Len(int function_code, unsigned int operations_number)
{
unsigned int respone_len = 0;
if (function_code == 0x0F || function_code == 0x10)
return respone_len;
if (function_code == 0x01) //读线圈
{
respone_len = operations_number / 8;
if (operations_number % 8)
respone_len++;
}
if (function_code == 0x03)
respone_len = operations_number * 2;
return respone_len;
}
/*********************************************************************************************
* 功能    : 检测响应报文长度
* 描述   : 对响应报文中存放长度字节进行判断和请求报文对比
* 输入 : Response_Message 响应报文 Request_Message 请求报文 Response_Message_len 接收到的数据长度
* 输出 : true 长度正常 false 长度异常
*********************************************************************************************/
bool Check_Response_Message_len(UINT8 *Response_Message, UINT8 *Request_Message, int response_message_len)
{
if ((response_message_len - 6) != Response_Message[5])
return false;
unsigned int operations_Number = Request_Message[10] << 8 | Request_Message[11];
unsigned int respone_Len = Count_Respone_Len(Request_Message[7], operations_Number);
if (Request_Message[7] == 0x0F || Request_Message[7] == 0x10)
if (response_message_len != 12)
return false;
if (Request_Message[7] == 0x01 || Request_Message[7] == 0x03)
{
if (respone_Len + 9 != response_message_len)
return false;
if (respone_Len != Response_Message[8])
return false;
}
return true;
}

/*********************************************************************************************
* 功能    : 判断响应报文是否可以正常解析
* 描述   : 通过长度和异常码等判定该响应报文是否可以解析
* 输入 : Response_Message 响应报文 Request_Message请求报文 Response_Message_len 响应报文长度
* 输出 : 响应数据类型
*********************************************************************************************/
int Analysis_Response_Message(UINT8 *Response_Message, UINT8 *Request_Message, int response_message_len)
{
if (response_message_len < 9 || response_message_len > 260)
return MSG_LEN_ERROR;
for (int i = 0; i < 7; i++)
{
if (i == 4 || i == 5) //后续字节长度
continue;
if (Response_Message[i] != Request_Message[i]) //0 1 传输标识,2 3 协议标识,6设备ID
return MABP_ERROR; //一旦不一致,判定为异常报文数据
}
if (Response_Message[4] != 0x00) //4 固定0x00
return MABP_ERROR;

if (Response_Message[7] == Request_Message[7] + 0x80)//先处理异常响应
{
if (response_message_len == 9)
{
return ABNORMAL_RESPONSE;
}
else
return MSG_LEN_ERROR;
}
if (Response_Message[7] != Request_Message[7]) //功能码判断
return FUNCTION_CODE_ERROR;
if (Request_Message[7] == 0x0F || Request_Message[7] == 0x10) //0F 10 地址和操作数量判定
{
for (int j = 8; j < 10; j++)
{
if (Request_Message[j] != Response_Message[j])
return START_ADDRESS_ERROR;
}
for (int j = 10; j < 12; j++)
{
if (Request_Message[j] != Response_Message[j])
return OPERATION_NUMBER_ERROR;
}
}
if (!Check_Response_Message_len(Response_Message, Request_Message, response_message_len))
return MSG_LEN_ERROR;
return NORMAL_RESPONSE;
}

/*********************************************************************************************
* 功能    : 生成MBAP报头
* 描述 : MBAP报文头的包括的内容:
* +-------------+---------+--------+--------+------------------------------+
* | 域 | 长度 | 客户机 | 服务器 | 描述 |
* +-------------+---------+--------+--------+------------------------------+
* |事务元标识符 | 2个字节 | 启动 | 复制 |请求/响应事务处理的识别码 |
* +-------------+---------+--------+--------+------------------------------+
* |协议标识符 | 2个字节 | 启动 | 复制 |0=MODBUS 协议 |
* +-------------+---------+--------+--------+------------------------------+
* | 长度 | 2个字节 | 启动 | 启动 |以下字节的数量 |
* +-------------+---------+--------+--------+------------------------------+
* |单元标识符 | 1个字节 | 启动 | 复制 |连接的远程从站的识别码 |
* 输入 : 无
* 输出 : MBAP报文头内容
*********************************************************************************************/
void Create_MBAP(UINT8 *Message, int function_code, unsigned int operations_number)
{
Message[0] = Transmission_Indicator >> 8;//事务号
Message[1] = (UINT8)Transmission_Indicator;
Transmission_Indicator++;
Message[2] = 0x00; //Modbus协议标识
Message[3] = 0x00;
Message[4] = 0x00;//后续字节长度
Message[5] = Count_Write_date_number(function_code, operations_number) + 0x06;
if (function_code == 0x0F || function_code == 0x10)//0f/10功能码后续字节数多1
{
Message[5] = Message[5] + 1;
}
Message[6] = DEVICE_ID;
}

/*********************************************************************************************
* 功能    : 字符串转UINT8类型
* 描述   : 根据写入数量和功能码类型输入相应的数据
* 输入 : *Message 消息帧存放的数组 Write_date 要转换的字符串
* Message_len消息帧数组的起始位置
* 输出 : Message_len 消息帧的长度
*********************************************************************************************/
int HexStringtoByte(UINT8 *Message, string write_date, int message_len, int function_code, unsigned int operations_Number)
{
if (write_date.length() == 0)
return message_len;
Message[message_len] = Count_Write_date_number(function_code, operations_Number);
message_len++;
const char *b = write_date.c_str();
int temp = 0;
for (unsigned int i = 0; i + 3 < write_date.length(); i = i + 3)
{
sscanf_s(b + i, "%02X", &temp);
Message[message_len] = (UINT8)temp;
message_len++;
}
sscanf_s(b + write_date.length() - 2, "%02X", &temp);
Message[message_len] = (UINT8)temp;
return ++message_len;
}

/*********************************************************************************************
* 功能    : 生成TCP模式下的消息帧
* 描述   : 根据要写入的数据生成消息帧
* 输入 : *Message 消息帧存放的数组 Write_date 写入数据的字符串
* Function_code 功能码 Operations_Number 操作数量 Starting_address起始地址
* 输出 : 消息帧的总长度
*********************************************************************************************/
int Create_TCP_Message(UINT8 *Message, int function_code, unsigned int operations_Number, unsigned int starting_address, string write_date)
{

Create_MBAP(Message, function_code, operations_Number);
Message[7] = function_code;//功能码
Message[8] = starting_address >> 8;//起始地址H
Message[9] = starting_address;//起始地址L
Message[10] = operations_Number >> 8;//操作数量H
Message[11] = operations_Number;//操作数量L
return HexStringtoByte(Message, write_date, 12, function_code, operations_Number);

}

/*********************************************************************************************
* 功能    : 运行客户端
* 描述   : 初始化并且生成发送请求等待响应
* 输入 : 无
* 输出 : 无
*********************************************************************************************/
int Tcp_Client()
{
SOCKET clientSocket;
UINT8 Request_Message[600];
memset(Request_Message, 0, 600);
UINT8 Response_Message[600];
memset(Response_Message, 0, 600);

do
{
clientSocket = Init_Client();
} while (INVALID_SOCKET == clientSocket);

while (true)
{
int function_code = Input_Function_code();//交互
unsigned int operations_Number = Input_Operations_number(function_code);
unsigned int starting_address = Input_Starting_address();
string write_date = Input_Write_date(function_code, operations_Number);
int request_message_len = Create_TCP_Message(Request_Message, function_code, operations_Number, starting_address, write_date);//生成
if (!Send_date(clientSocket, Request_Message, request_message_len)) //发送
{
if (Abnormal_Connection(&clientSocket))
continue;
else
break;
}
int response_message_len = Recv_date(clientSocket, Response_Message);//接收
if (response_message_len)
{
int flage = Analysis_Response_Message(Response_Message, Request_Message, response_message_len);
Printf_Interactive_Data(Response_Message, Request_Message, flage, request_message_len, response_message_len);
}
else if(!Test_Connection_status(clientSocket))
{
if (Abnormal_Connection(&clientSocket))
continue;
else
break;
}
else
printf("响应超时\n");

printf("**************************** Press Enter To Contioun ****************************\n");
getchar();
system("cls");
}
//关闭套接字
closesocket(clientSocket);
//关闭服务
WSACleanup();
return 0;
}

+ 12
- 0
Modbus_communication/Modbus_TCP/Modbus_Master.h View File

@@ -0,0 +1,12 @@
#ifndef __MODBUS_MASTER_H
#define __MODBUS_MASTER_H

#include "TCP_client.h"
#include "Interactive.h"
#define DEVICE_ID 0x01 //É豸ID

int Tcp_Client();
int Create_TCP_Message(UINT8 *Message, int function_code, unsigned int operations_Number, unsigned int starting_address, string write_date);
int Analysis_Response_Message(UINT8 *Response_Message, UINT8 *Request_Message, int response_message_len);

#endif

+ 6
- 4
Modbus_communication/Modbus_TCP/Modbus_TCP.vcxproj View File

@@ -66,14 +66,16 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="common.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="TCP_client.cpp" />
<ClCompile Include="Interactive.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="Modbus_Master.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="common.h" />
<ClInclude Include="main.h" />
<ClInclude Include="TCP_client.h" />
<ClInclude Include="Interactive.h" />
<ClInclude Include="main.h" />
<ClInclude Include="Modbus_Master.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">


+ 10
- 4
Modbus_communication/Modbus_TCP/Modbus_TCP.vcxproj.filters View File

@@ -18,7 +18,10 @@
<ClCompile Include="main.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="common.cpp">
<ClCompile Include="Interactive.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="Modbus_Master.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="TCP_client.cpp">
@@ -26,13 +29,16 @@
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="common.h">
<ClInclude Include="main.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="TCP_client.h">
<ClInclude Include="Interactive.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="main.h">
<ClInclude Include="Modbus_Master.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="TCP_client.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>

+ 143
- 250
Modbus_communication/Modbus_TCP/TCP_client.cpp View File

@@ -1,303 +1,196 @@
#include "TCP_client.h"
UINT16 Transmission_Indicator = 0x00; //事务号

/*********************************************************************************************
* 功能    : 打印读取从站的线圈状态
* 描述   : 对响应报文中的数据进行解析和显示
* 输入 : Response_Message 响应报文 Request_Message 请求报文
* 输出 : 无
*********************************************************************************************/
void Printf_Coil_date(UINT8 *Response_Message, UINT8 *Request_Message)
{
printf("从站设备ID %02X 功能码为 %02X\n", Response_Message[6], Response_Message[7]);
unsigned int temp1 = ((Request_Message[8] << 8) | Request_Message[9]);
unsigned int number = ((Request_Message[10] << 8) | Request_Message[11]);
printf("线圈起始地址为%d \n",temp1);
unsigned int temp = temp1;
for (int i = 0; i < Response_Message[8]; i++)
{
unsigned int temp2 = temp + 7;
if (temp2 > temp1 + number - 1)
temp2 = temp1 + number - 1;
printf("线圈%d --- %d的状态为:%02X \n", temp2, temp, Response_Message[9+i]);
temp = temp + 8;
}
}

/*********************************************************************************************
* 功能    : 打印读取从站的寄存器状态
* 描述   : 对响应报文中的数据进行解析和显示
* 输入 : Response_Message 响应报文 Request_Message 请求报文
* 输出 : 无
*********************************************************************************************/
void Printf_Register_date(UINT8 *Response_Message, UINT8 *Request_Message)
{
printf("从站设备ID %02X 功能码为 %02X\n", Response_Message[6], Response_Message[7]);
unsigned int temp1 = ((Request_Message[8] << 8) | Request_Message[9]);
printf("寄存器起始地址为%d \n", temp1);
for (int i = 0; i < Response_Message[8]; i = i + 2)
{
printf("寄存器%d的值为:%02X %02X \n", temp1++, Response_Message[9 + i], Response_Message[10+i]);
}
}

/*********************************************************************************************
* 功能    : 打印读取异常响应报文信息
* 描述   : 对响应报文中的数据进行解析和显示
* 输入 : Response_Message 响应报文
* 输出 : 无
* 功能    : IP地址有效性检测
* 描述   : 检测输入的IP地址是否合法
* 输入 : IP 输入的IP地址
* 输出 : true IP地址合法
* false IP地址非法
*********************************************************************************************/
void Printf_Anomaly_date(UINT8 *Response_Message)
bool Check_IP(string ip)
{
UINT8 anomaly_code = Response_Message[8];
printf("从站设备ID %02X 功能码为 %02X\n", Response_Message[6], Response_Message[7]);
switch (anomaly_code)
int s[4];
if (ip.length() < 7 || ip.length() > 15) //长度判定
return false;
if (sscanf_s(ip.c_str(), "%d.%d.%d.%d", &s[0], &s[1], &s[2], &s[3]) != 4) //IPV4格式正确
{
case 0x01: printf("%02X : 从站设备不支持此功能码\n", anomaly_code); break;
case 0x02: printf("%02X : 指定的数据地址在从站设备中不存在\n", anomaly_code); break;
case 0x03: printf("%02X : 指定的数据超过范围或者不允许使用\n", anomaly_code); break;
case 0x04: printf("%02X : 从站设备处理响应的过程中,出现未知错误等\n", anomaly_code); break;
default: printf("Unkown Other Error!!!!!\n");
return false;
}
}

/*********************************************************************************************
* 功能    : 检测响应报文长度
* 描述   : 对响应报文中存放长度字节进行判断和请求报文对比
* 输入 : Response_Message 响应报文 Request_Message 请求报文 Response_Message_len 接收到的数据长度
* 输出 : true 长度正常 false 长度异常
*********************************************************************************************/
bool Check_Response_Message_len(UINT8 *Response_Message, UINT8 *Request_Message, int response_message_len)
{
if ((response_message_len - 6) != Response_Message[5])
string newip = to_string(s[0]) + "." + to_string(s[1]) + "." + to_string(s[2]) + "." + to_string(s[3]);
if (ip != newip) //前导0
return false;
unsigned int operations_Number = Request_Message[10] << 8 | Request_Message[11];
unsigned int respone_Len = Count_Respone_Len(Request_Message[7], operations_Number);
if (Request_Message[7] == 0x0F || Request_Message[7] == 0x10)
if (response_message_len != 12)
return false;
if (Request_Message[7] == 0x01 || Request_Message[7] == 0x03)
if ((s[0] & 0xffffff00) || (s[1] & 0xffffff00) || (s[2] & 0xffffff00) || (s[3] & 0xffffff00)) //判断每一段大小是否符合要求
{
if (respone_Len + 9 != response_message_len)
return false;
if (respone_Len != Response_Message[8])
return false;
return false;
}
return true;
}

bool Printf_Analysis_Outcome(UINT8 *Response_Message, UINT8 *Request_Message)
{
switch (Response_Message[7])
{
case 0x01:Printf_Coil_date(Response_Message, Request_Message); break;
case 0x03:Printf_Register_date(Response_Message, Request_Message); break;
case 0x0F:printf("成功写入从站线圈%d个\n", ((Request_Message[10] << 8) | Request_Message[11])); break;
case 0x10:printf("成功写入从站寄存器%d个\n", ((Request_Message[10] << 8) | Request_Message[11])); break;
default: return false;
}
return true;
}
/*********************************************************************************************
* 功能    : 判断响应报文是否可以正常解析
* 描述   : 通过长度和异常码等判定该响应报文是否可以解析
* 输入 : Response_Message 响应报文 Request_Message请求报文 Response_Message_len 响应报文长度
* 输出 : true可以正常解析 false 无法解析
* 功能    : 获取从站IP地址和端口号
* 描述   : 终端输入从站IP地址和端口号
* 输入 : IP 地址 (IPV4)
* *Port_number 端口号(1-65535)
* 输出 : 无
*********************************************************************************************/
bool Analysis_Response_Message(UINT8 *Response_Message, UINT8 *Request_Message, int response_message_len)
void Input_IP(string& ip, unsigned int *port_number)
{
if (response_message_len < 9 || response_message_len > 260)
return false;
for (int i = 0; i < 7; i++)
{
if (i == 4 || i == 5) //后续字节长度
continue;
if (Response_Message[i] != Request_Message[i]) //0 1 传输标识,2 3 协议标识,6设备ID
return false; //一旦不一致,判定为异常报文数据
}
if (Response_Message[4] != 0x00) //4 固定0x00
return false;

if (Response_Message[7] == Request_Message[7] + 0x80)//先处理异常响应
int i = 1;
do
{
if (response_message_len == 9)
if (i == 1)
{
Printf_Anomaly_date(Response_Message);
return true;
cout << "请输入从站IP:";
i = 0;
}
else
return false;
}
if (Response_Message[7] != Request_Message[7]) //功能码判断
return false;
if (Request_Message[7] == 0x0F || Request_Message[7] == 0x10) //0F 10 地址和操作数量判定
{
for (int j = 8; j < 12; j++)
{
if (Request_Message[j] != Response_Message[j])
return false;
}
}
if (!Check_Response_Message_len(Response_Message, Request_Message, response_message_len))
return false;
//打印解析结果
return Printf_Analysis_Outcome(Response_Message, Request_Message);
}

cout << "IP地址格式不正确,请重新输入从站IP:";
cin >> ip;
} while (!Check_IP(ip));

void Printf_Message(UINT8 *Message,int flage, int message_len)
{
if (flage == 1)
printf("主站请求 :");
else
printf("从站响应 :");
for (int i = 0; i < message_len; i++)
i = 1;
cout << "IP地址输格式入正确,请输入从站端口号:";
do
{
printf("%02x ", Message[i]);
}
printf("\n");
if (LOG_NOTE_SWITCH)
Log_Note(Message, flage, message_len);
}

if (i != 1)
cout << "请重新输入从站端口号:";
cin >> *port_number;
i = 0;
} while (*port_number == 0 || *port_number > 65535); //端口不能为0 ,端口号范围1---65535

}
/*********************************************************************************************
* 功能    : 生成MBAP报头
* 描述 : MBAP报文头的包括的内容:
* +-------------+---------+--------+--------+------------------------------+
* | 域 | 长度 | 客户机 | 服务器 | 描述 |
* +-------------+---------+--------+--------+------------------------------+
* |事务元标识符 | 2个字节 | 启动 | 复制 |请求/响应事务处理的识别码 |
* +-------------+---------+--------+--------+------------------------------+
* |协议标识符 | 2个字节 | 启动 | 复制 |0=MODBUS 协议 |
* +-------------+---------+--------+--------+------------------------------+
* | 长度 | 2个字节 | 启动 | 启动 |以下字节的数量 |
* +-------------+---------+--------+--------+------------------------------+
* |单元标识符 | 1个字节 | 启动 | 复制 |连接的远程从站的识别码 |
* 功能    : socket版本
* 描述   : 启动socket服务
* 输入 : 无
* 输出 : MBAP报文头内容
* 输出 : true 启动成功
* false 启动失败
*********************************************************************************************/
void Create_MBAP(UINT8 *Message, int function_code, unsigned int operations_number)
bool InitSocket_Version(void)
{
Message[0] = Transmission_Indicator >> 8;//事务号
Message[1] = (UINT8)Transmission_Indicator;
Transmission_Indicator++;
Message[2] = 0x00; //Modbus协议标识
Message[3] = 0x00;
Message[4] = 0x00;//后续字节长度
Message[5] = Count_Write_date_number(function_code, operations_number) + 0x06;
if (function_code == 0x0F || function_code == 0x10)//0f/10功能码后续字节数多1
WORD sockVersion = MAKEWORD(2, 2);//使用winsocket2.2版本
WSADATA wsaData;
if (WSAStartup(sockVersion, &wsaData) != 0)
{
Message[5] = Message[5] + 1;
return false;
}
Message[6] = DEVICE_ID;
return true;
}

/*********************************************************************************************
* 功能    : 字符串转UINT8类型
* 描述   : 根据写入数量和功能码类型输入相应的数据
* 输入 : *Message 消息帧存放的数组 Write_date 要转换的字符串
* Message_len消息帧数组的起始位置
* 输出 : Message_len 消息帧的长度
* 功能    : 初始化客户端
* 描述   : 根据终端输入从站IP地址和端口号连接对应的服务器,设置超时时间
* 输入 : 无
* 输出 : ClientSocket 连接成功的套接字
*********************************************************************************************/
int HexStringtoByte(UINT8 *Message, string write_date, int message_len, int function_code, unsigned int operations_Number)
SOCKET Init_Client(void)
{
if (write_date.length() == 0)
return message_len;
Message[message_len] = Count_Write_date_number(function_code, operations_Number);
message_len++;
const char *b = write_date.c_str();
int temp = 0;
for (unsigned int i = 0; i + 3 < write_date.length(); i = i + 3)
if (InitSocket_Version() == 0)
{
printf("启动Socket服务失败,请检查Socket版本");
return INVALID_SOCKET;
}
string ip_address;
unsigned int port_number;
Input_IP(ip_address, &port_number);
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in serversock_in;
serversock_in.sin_addr.S_un.S_addr = inet_addr(ip_address.c_str());
serversock_in.sin_family = AF_INET;
serversock_in.sin_port = htons(port_number);
if (SOCKET_ERROR == connect(clientSocket, (SOCKADDR*)&serversock_in, sizeof(SOCKADDR)))
{
sscanf_s(b + i, "%02X", &temp);
Message[message_len] = (UINT8)temp;
message_len++;
cout << "尝试连接TCP从站失败" << endl;
return INVALID_SOCKET;
}
sscanf_s(b + write_date.length() - 2, "%02X", &temp);
Message[message_len] = (UINT8)temp;
return ++message_len;
cout << "连接TCP从站成功" << endl;
TIMEVAL timeout;
timeout.tv_sec = 200; //ms
timeout.tv_usec = 0; //us
setsockopt(clientSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));//设置接收超时时间
return clientSocket;
}

/*********************************************************************************************
* 功能    : 生成TCP模式下的消息帧
* 描述   : 根据要写入的数据生成消息帧
* 输入 : *Message 消息帧存放的数组 Write_date 写入数据的字符串
* Function_code 功能码 Operations_Number 操作数量 Starting_address起始地址
* 输出 : 消息帧的总长度
*********************************************************************************************/
int Create_TCP_Message(UINT8 *Message, int function_code, unsigned int operations_Number, unsigned int starting_address, string write_date)
void Clear_buf(SOCKET clientSocket)
{

Create_MBAP(Message, function_code, operations_Number);
Message[7] = function_code;//功能码
Message[8] = starting_address >> 8;//起始地址H
Message[9] = starting_address;//起始地址L
Message[10] = operations_Number >> 8;//操作数量H
Message[11] = operations_Number;//操作数量L

return HexStringtoByte(Message, write_date, 12, function_code, operations_Number);
unsigned long bytesToRecv;
char temp[500];
do
{
ioctlsocket(clientSocket, FIONREAD, &bytesToRecv);
if (bytesToRecv != 0)//不等于0时进行清理操作
{
if (bytesToRecv > 500)
{
recv(clientSocket, temp, 500, 0);
}
else
recv(clientSocket, temp, bytesToRecv, 0);
}
} while (bytesToRecv != 0);

}

/*********************************************************************************************
* 功能    : 运行客户端
* 描述   : 初始化并且生成发送请求等待响应
* 输入 : 无
* 输出 : 无
*********************************************************************************************/
int Tcp_Client()
bool Send_date(SOCKET clientSocket, UINT8 *Request_Message, int request_message_len)
{
SOCKET clientSocket;
UINT8 Request_Message[600];
memset(Request_Message, 0, 600);
UINT8 Response_Message[600];
memset(Response_Message, 0, 600);
Clear_buf(clientSocket); //清理缓冲区
int status = send(clientSocket, (char*)Request_Message, request_message_len, 0);
if (status == (-1))
{
return false;
}
return true;
}

bool Abnormal_Connection(SOCKET *clientSocket)
{
printf("连接异常,请检查连接状态。\n");
printf("**************************** Press Enter To Contioun ****************************\n");
getchar();
system("cls");
closesocket(*clientSocket);
WSACleanup();
printf("是否重新连接服务器: 1 重新连接 0 关闭本软件\n");
int flage = 0;
do
{
clientSocket = Init_Client();
} while (INVALID_SOCKET == clientSocket);

while (true)
cin >> flage;
cin.clear();
cin.sync();
} while (!(flage == 0 || flage == 1));
if (flage == 0)
return false;
system("cls");
do
{
int function_code = Input_Function_code();//交互
unsigned int operations_Number = Input_Operations_number(function_code);
unsigned int starting_address = Input_Starting_address();
string write_date = Input_Write_date(function_code, operations_Number);
int request_message_len = Create_TCP_Message(Request_Message, function_code, operations_Number, starting_address, write_date);//生成
if (!Send_date(clientSocket, Request_Message, request_message_len)) //发送
{
if (Abnormal_Connection(&clientSocket))
continue;
else
break;
}
int Response_Message_len = Recv_date(clientSocket, Response_Message);//接收
Printf_Message(Request_Message, 1, request_message_len);
Printf_Message(Response_Message, 0, Response_Message_len);
if (Response_Message_len)
{
if (!Analysis_Response_Message(Response_Message, Request_Message, Response_Message_len))
printf("响应报文数据异常\n");
}
else if(!Test_Connection_status(clientSocket))
{
if (Abnormal_Connection(&clientSocket))
continue;
else
break;
}
else
printf("响应超时\n");
*clientSocket = Init_Client();
} while (INVALID_SOCKET == *clientSocket);
system("cls");
return true;
}

printf("**************************** Press Enter To Contioun ****************************\n");
getchar();
system("cls");
int Recv_date(SOCKET clientSocket, UINT8 *Response_Message)
{
int Response_Message_len = recv(clientSocket, (char*)Response_Message, 600, 0);
if (Response_Message_len > 0)
{
return Response_Message_len;
}
//关闭套接字
closesocket(clientSocket);
//关闭服务
WSACleanup();
return 0;
}

bool Test_Connection_status(SOCKET clientSocket)
{
TIMEVAL timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
fd_set reads;
FD_ZERO(&reads);
FD_SET(clientSocket, &reads);
if (select(0, &reads, 0, 0, &timeout))
return false;
else
return true;
}

+ 14
- 4
Modbus_communication/Modbus_TCP/TCP_client.h View File

@@ -1,11 +1,21 @@
#ifndef __TCP_CLIENT_H
#define __TCP_CLIENT_H

#include "common.h"
#include <stdio.h>
#include <winsock2.h>
#include <WS2tcpip.h>
#include <vector>
#include <string>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;

unsigned int Count_Respone_Len(int function_code, unsigned int operations_number);
SOCKET Init_Client(void);
bool Send_date(SOCKET clientSocket, UINT8 *Request_Message, int request_message_len);
bool Abnormal_Connection(SOCKET *clientSocket);
int Recv_date(SOCKET clientSocket, UINT8 *Response_Message);
bool Test_Connection_status(SOCKET clientSocket);

int Tcp_Client();
int Create_TCP_Message(UINT8 *Message, int function_code, unsigned int operations_Number, unsigned int starting_address, string write_date);
bool Analysis_Response_Message(UINT8 *Response_Message, UINT8 *Request_Message, int response_message_len);

#endif

+ 1
- 1
Modbus_communication/Modbus_TCP/main.h View File

@@ -1,6 +1,6 @@
#ifndef __MAIN_H
#define __MAIN_H

#include "TCP_client.h"
#include "Modbus_Master.h"

#endif

+ 10
- 10
Modbus_communication/Modbus_communication.sln View File

@@ -7,9 +7,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Modbus_RTU_Salve", "Modbus_
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Modbus_TCP", "Modbus_TCP\Modbus_TCP.vcxproj", "{CC08BE54-3DFF-41F2-9F8B-17E0FD5E3757}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TCP_Master_test", "TCP_Master_test\TCP_Master_test.vcxproj", "{677F6F19-D890-4DE8-9EFD-08FE0E154AD0}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Master_Salve_DLL", "Master_Salve_DLL\Master_Salve_DLL.vcxproj", "{CB8E0444-CD69-430B-8ACF-8083D140A65F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RTU_Salve_test", "RTU_Salve_test\RTU_Salve_test.vcxproj", "{4443732F-F883-4E71-ACDD-E5E777C63728}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTest_DLL", "UnitTest_DLL\UnitTest_DLL.vcxproj", "{83299DA7-142F-4A47-B239-4B5C31E5FD86}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -25,14 +25,14 @@ Global
{CC08BE54-3DFF-41F2-9F8B-17E0FD5E3757}.Debug|Win32.Build.0 = Debug|Win32
{CC08BE54-3DFF-41F2-9F8B-17E0FD5E3757}.Release|Win32.ActiveCfg = Release|Win32
{CC08BE54-3DFF-41F2-9F8B-17E0FD5E3757}.Release|Win32.Build.0 = Release|Win32
{677F6F19-D890-4DE8-9EFD-08FE0E154AD0}.Debug|Win32.ActiveCfg = Debug|Win32
{677F6F19-D890-4DE8-9EFD-08FE0E154AD0}.Debug|Win32.Build.0 = Debug|Win32
{677F6F19-D890-4DE8-9EFD-08FE0E154AD0}.Release|Win32.ActiveCfg = Release|Win32
{677F6F19-D890-4DE8-9EFD-08FE0E154AD0}.Release|Win32.Build.0 = Release|Win32
{4443732F-F883-4E71-ACDD-E5E777C63728}.Debug|Win32.ActiveCfg = Debug|Win32
{4443732F-F883-4E71-ACDD-E5E777C63728}.Debug|Win32.Build.0 = Debug|Win32
{4443732F-F883-4E71-ACDD-E5E777C63728}.Release|Win32.ActiveCfg = Release|Win32
{4443732F-F883-4E71-ACDD-E5E777C63728}.Release|Win32.Build.0 = Release|Win32
{CB8E0444-CD69-430B-8ACF-8083D140A65F}.Debug|Win32.ActiveCfg = Debug|Win32
{CB8E0444-CD69-430B-8ACF-8083D140A65F}.Debug|Win32.Build.0 = Debug|Win32
{CB8E0444-CD69-430B-8ACF-8083D140A65F}.Release|Win32.ActiveCfg = Release|Win32
{CB8E0444-CD69-430B-8ACF-8083D140A65F}.Release|Win32.Build.0 = Release|Win32
{83299DA7-142F-4A47-B239-4B5C31E5FD86}.Debug|Win32.ActiveCfg = Debug|Win32
{83299DA7-142F-4A47-B239-4B5C31E5FD86}.Debug|Win32.Build.0 = Debug|Win32
{83299DA7-142F-4A47-B239-4B5C31E5FD86}.Release|Win32.ActiveCfg = Release|Win32
{83299DA7-142F-4A47-B239-4B5C31E5FD86}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE


+ 0
- 106
Modbus_communication/RTU_Salve_test/RTU_Test_Code.cpp View File

@@ -1,106 +0,0 @@
#include "RTU_Test_Code.h"

/*********************************************************************************************
* Function Test 1: Parsing Request Message
*********************************************************************************************/
void Parsing_Request_Message_Test(void)
{
char buf[LEN];
CString name = "Example";
char s[10] = "";
int Input1;
int j = 0;
int number = GetPrivateProfileInt(name, "Number", 0, TESTPATH3);
for (int i = 1; i < number + 1; i++)
{
memset(buf, 0, sizeof(buf));
memset(s, 0, sizeof(s));
_itoa_s(i, s, 10);
CString name1 = name + s;
Input1 = GetPrivateProfileString(name1, "Input1", "", buf, LEN, TESTPATH3);

UINT8 Requst_Message[300];
UINT8 Response_Message[300];
string Act_Message = buf;
const char *b = Act_Message.c_str();
unsigned int Act_len = 0;
for (unsigned int i = 0; i + 3 < Act_Message.length(); i = i + 3)
{
sscanf_s(b + i, "%02X", (int *)(Requst_Message + Act_len));
Act_len++;
}
sscanf_s(b + Act_Message.length() - 2, "%02X", (int *)(Requst_Message + Act_len));
//bool Create_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, DWORD Read_len)
bool a = Create_Response_Message(Requst_Message, Response_Message, Act_len+1);
j++;
printf("%d---%d\n", j, a);
}
}

/*********************************************************************************************
* Function Test 2: Create Response Message
*********************************************************************************************/
void Create_Response_Message_Test(void)
{
char buf[LEN];
char buf1[LEN];
CString name = "Example";
char s[10] = "";
int Input1, Input2;
int number = GetPrivateProfileInt(name, "Number", 0, TESTPATH3);
Init_Coil_Register();
for (int i = 1; i < number + 1; i++)
{
memset(buf, 0, sizeof(buf));
memset(buf1, 0, sizeof(buf1));
memset(s, 0, sizeof(s));
_itoa_s(i, s, 10);
CString name1 = name + s;
Input1 = GetPrivateProfileString(name1, "Input1", "", buf, LEN, TESTPATH3);
Input2 = GetPrivateProfileString(name1, "Output", "", buf1, LEN, TESTPATH3);

UINT8 Request_Message[300];
memset(Request_Message, 0, 300);
string Act_Message = buf;
const char *b = Act_Message.c_str();
unsigned int Act_len = 0;
for (unsigned int i = 0; i + 3 < Act_Message.length(); i = i + 3)
{
sscanf_s(b + i, "%02X", (int *)(Request_Message + Act_len));
Act_len++;
}
sscanf_s(b + Act_Message.length() - 2, "%02X", (int *)(Request_Message + Act_len));


UINT8 Act_Response_Message[300];
memset(Act_Response_Message, 0, 300);
unsigned int Act_len1 = 0;
if (Input2 != 0)
{
string Act_Message1 = buf1;
const char *a = Act_Message1.c_str();
for (unsigned int i = 0; i + 3 < Act_Message1.length(); i = i + 3)
{
sscanf_s(a + i, "%02X", (int *)(Act_Response_Message + Act_len1));
Act_len1++;
}
sscanf_s(a + Act_Message1.length() - 2, "%02X", (int *)(Act_Response_Message + Act_len1));
}

UINT8 Response_Message[300];
memset(Response_Message, 0, 300);
Create_Response_Message(Request_Message, Response_Message, Act_len + 1);
printf("µÚ%d×éÑùÀý£º\n",i);
for (unsigned int j = 0; j < Act_len1 + 1; j++)
{
printf("%02X ", Act_Response_Message[j]);
}
printf("\n");
for (unsigned int m = 0; m < Act_len1 + 1; m++)
{
printf("%02X ", Response_Message[m]);
}
printf("\n");
printf("\n");
}
}

+ 0
- 14
Modbus_communication/RTU_Salve_test/RTU_Test_Code.h View File

@@ -1,14 +0,0 @@
#ifndef __RTU_TEST_CODE_H
#define __RTU_TEST_CODE_H

#include "../Modbus_RTU_Salve/RTU_Salve.h"
#include <windows.h>
#include <atlstr.h>

#define TESTPATH3 "./3.ini"
#define LEN 65535

void Parsing_Request_Message_Test(void);
void Create_Response_Message_Test(void);

#endif

+ 0
- 9
Modbus_communication/RTU_Salve_test/RTU_test.cpp View File

@@ -1,9 +0,0 @@
#include "RTU_Test_Code.h"

int main()
{
Parsing_Request_Message_Test();
Create_Response_Message_Test();
getchar();
return 0;
}

+ 0
- 98
Modbus_communication/TCP_Master_test/TCP_Test_Code.cpp View File

@@ -1,98 +0,0 @@
#include "TCP_Test_Code.h"

/*********************************************************************************************
* Function Test 1: Generate request message
*********************************************************************************************/
void Generate_request_message_test(void)
{
char buf[LEN];
char buf1[LEN];
CString name = "Example";
char s[10] = "";
int Output, Input1, Input2, Input3, Input4;

int number = GetPrivateProfileInt(name, "Number", 0, TESTPATH1);
for (int i = 1; i < number + 1; i++)
{
memset(buf, 0, sizeof(buf));
memset(buf1, 0, sizeof(buf1));
memset(s, 0, sizeof(s));
_itoa_s(i, s, 10);
CString name1 = name + s;
Input1 = GetPrivateProfileInt(name1, "Input1", 0, TESTPATH1);
Input2 = GetPrivateProfileInt(name1, "Input2", 0, TESTPATH1);
Input3 = GetPrivateProfileInt(name1, "Input3", 0, TESTPATH1);
Input4 = GetPrivateProfileString(name1, "Input4", "", buf, LEN, TESTPATH1);
Output = GetPrivateProfileString(name1, "Output", "", buf1, LEN, TESTPATH1);

UINT8 test_Message[300];
UINT8 Output_Message[300];
string Write_date = buf;
string Act_Message = buf1;
const char *b = Act_Message.c_str();
unsigned int Act_len = 0;
for (unsigned int i = 0; i + 3 < Act_Message.length(); i = i + 3)
{
sscanf_s(b + i, "%02X", (int *)(Output_Message + Act_len));
Act_len++;
}
sscanf_s(b + Act_Message.length() - 2, "%02X", (int *)(Output_Message + Act_len));
//int Create_TCP_Message(UINT8 *Message, int function_code, unsigned int operations_Number, unsigned int starting_address, string write_date);
int len = Create_TCP_Message(test_Message, Input1, Input2, Input3, Write_date);
for (int j = 0; j < len; j++)
{
if (test_Message[j] != Output_Message[j])
printf("--%d--loss--%d \n",i,j);
}

}
}

/*********************************************************************************************
* Function Test 2: Analysis response message
*********************************************************************************************/
void Analysis_response_message_test(void)
{
char buf[LEN];
char buf1[LEN];
CString name = "Example";
char s[10] = "";
int Input1, Input2;
int number = GetPrivateProfileInt(name, "Number", 0, TESTPATH2);
for (int i = 1; i < number + 1; i++)
{
memset(buf, 0, sizeof(buf));
memset(buf1, 0, sizeof(buf1));
memset(s, 0, sizeof(s));
_itoa_s(i, s, 10);
CString name1 = name + s;
Input1 = GetPrivateProfileString(name1, "Input1", "", buf, LEN, TESTPATH2);
Input2 = GetPrivateProfileString(name1, "Input2", "", buf1, LEN, TESTPATH2);

UINT8 Response_Message[300];
string Act_Message = buf1;
const char *b = Act_Message.c_str();
unsigned int Act_len = 0;
for (unsigned int i = 0; i + 3 < Act_Message.length(); i = i + 3)
{
sscanf_s(b + i, "%02X", (int *)(Response_Message + Act_len));
Act_len++;
}
sscanf_s(b + Act_Message.length() - 2, "%02X", (int *)(Response_Message + Act_len));


UINT8 Request_Message[300];
string Act_Message1 = buf;
const char *a = Act_Message1.c_str();
unsigned int Act_len1 = 0;
for (unsigned int i = 0; i + 3 < Act_Message1.length(); i = i + 3)
{
sscanf_s(a + i, "%02X", (int *)(Request_Message + Act_len1));
Act_len1++;
}
sscanf_s(a + Act_Message1.length() - 2, "%02X", (int *)(Request_Message + Act_len1));
Analysis_Response_Message(Response_Message, Request_Message, Act_len+1);
}
}



+ 0
- 16
Modbus_communication/TCP_Master_test/TCP_Test_Code.h View File

@@ -1,16 +0,0 @@
#ifndef __TCP_TEST_CODE_H
#define __TCP_TEST_CODE_H

#include <stdio.h>
#include "../Modbus_TCP/common.h"
#include "../Modbus_TCP/TCP_client.h"
#include <windows.h>
#include <atlstr.h>

#define TESTPATH1 "./1.ini"
#define TESTPATH2 "./2.ini"
#define LEN 65535

void Generate_request_message_test(void);
void Analysis_response_message_test(void);
#endif

Modbus_communication/TCP_Master_test/TCP_Test.cpp → Modbus_communication/UnitTest_DLL/TCP_Test.cpp View File


Modbus_communication/RTU_Salve_test/RTU_Salve_test.vcxproj → Modbus_communication/UnitTest_DLL/UnitTest_DLL.vcxproj View File

@@ -11,22 +11,25 @@
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{4443732F-F883-4E71-ACDD-E5E777C63728}</ProjectGuid>
<RootNamespace>RTU_Salve_test</RootNamespace>
<ProjectGuid>{83299DA7-142F-4A47-B239-4B5C31E5FD86}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>UnitTest_DLL</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -38,42 +41,57 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<UseFullPaths>true</UseFullPaths>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<UseFullPaths>true</UseFullPaths>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\Modbus_RTU_Salve\common.cpp" />
<ClCompile Include="..\Modbus_RTU_Salve\RTU_Salve.cpp" />
<ClCompile Include="RTU_test.cpp" />
<ClCompile Include="RTU_Test_Code.cpp" />
<ClCompile Include="master_salve_test.cpp" />
<ClCompile Include="unittest1.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Master_Salve_DLL\Master_Salve_DLL.vcxproj">
<Project>{cb8e0444-cd69-430b-8acf-8083d140a65f}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Modbus_RTU_Salve\common.h" />
<ClInclude Include="..\Modbus_RTU_Salve\RTU_Salve.h" />
<ClInclude Include="RTU_Test_Code.h" />
<ClInclude Include="master_salve_test.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

Modbus_communication/RTU_Salve_test/RTU_Salve_test.vcxproj.filters → Modbus_communication/UnitTest_DLL/UnitTest_DLL.vcxproj.filters View File

@@ -15,27 +15,15 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="RTU_test.cpp">
<ClCompile Include="unittest1.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="RTU_Test_Code.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="..\Modbus_RTU_Salve\common.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="..\Modbus_RTU_Salve\RTU_Salve.cpp">
<ClCompile Include="master_salve_test.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="RTU_Test_Code.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\Modbus_RTU_Salve\common.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\Modbus_RTU_Salve\RTU_Salve.h">
<ClInclude Include="master_salve_test.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>

+ 217
- 0
Modbus_communication/UnitTest_DLL/master_salve_test.cpp View File

@@ -0,0 +1,217 @@
#include "master_salve_test.h"

void Test_Master_Create_Request_Msg(void)
{
char buf[LEN];
char buf1[LEN];
CString name = "Example";
char s[10] = "";
int Output, Input1, Input2, Input3, Input4;
bool test_Value = true;
int number = GetPrivateProfileInt(name, "Number", 0, TESTPATH1);
for (int i = 1; i < number + 1; i++)
{
memset(buf, 0, sizeof(buf));
memset(buf1, 0, sizeof(buf1));
memset(s, 0, sizeof(s));
_itoa_s(i, s, 10);
CString name1 = name + s;
Input1 = GetPrivateProfileInt(name1, "Input1", 0, TESTPATH1);
Input2 = GetPrivateProfileInt(name1, "Input2", 0, TESTPATH1);
Input3 = GetPrivateProfileInt(name1, "Input3", 0, TESTPATH1);
Input4 = GetPrivateProfileString(name1, "Input4", "", buf, LEN, TESTPATH1);
Output = GetPrivateProfileString(name1, "Output", "", buf1, LEN, TESTPATH1);

UINT8 test_Message[300];
UINT8 Output_Message[300];
string Write_date = buf;
string Act_Message = buf1;
const char *b = Act_Message.c_str();
unsigned int Act_len = 0;
int temp = 0x00;
for (unsigned int i = 0; i + 3 < Act_Message.length(); i = i + 3)
{
sscanf_s(b + i, "%02X", &temp);
Output_Message[Act_len] = (UINT8)temp;
Act_len++;
}
sscanf_s(b + Act_Message.length() - 2, "%02X",&temp);
Output_Message[Act_len] = (UINT8)temp;
//int Create_TCP_Message(UINT8 *Message, int function_code, unsigned int operations_Number, unsigned int starting_address, string write_date);
int len = Create_TCP_Message(test_Message, Input1, Input2, Input3, Write_date);
for (int j = 0; j < len; j++)
{
if (test_Message[j] != Output_Message[j])
{
test_Value = false;
break;
}
}

Assert::AreEqual(test_Value,true);
}
}

void Test_Master_Analysis_Response_Msg(void)
{
char buf[LEN];
char buf1[LEN];
CString name = "Example";
char s[10] = "";
int Input1, Input2, Output;
int number = GetPrivateProfileInt(name, "Number", 0, TESTPATH2);
for (int i = 1; i < number + 1; i++)
{
memset(buf, 0, sizeof(buf));
memset(buf1, 0, sizeof(buf1));
memset(s, 0, sizeof(s));
_itoa_s(i, s, 10);
CString name1 = name + s;
Input1 = GetPrivateProfileString(name1, "Input1", "", buf, LEN, TESTPATH2);
Input2 = GetPrivateProfileString(name1, "Input2", "", buf1, LEN, TESTPATH2);
Output = GetPrivateProfileInt(name1, "Output", 0, TESTPATH2);
//buf ÇëÇó buf1 ÏìÓ¦
UINT8 Request_Message[300];
string Act_Message = buf;
const char *a = Act_Message.c_str();
unsigned int Act_len = 0;
for (unsigned int i = 0; i + 3 < Act_Message.length(); i = i + 3)
{
sscanf_s(a + i, "%02X", (int *)(Request_Message + Act_len));
Act_len++;
}
sscanf_s(a + Act_Message.length() - 2, "%02X", (int *)(Request_Message + Act_len));


UINT8 Response_Message[300];
string Act_Message1 = buf1;
const char *b = Act_Message1.c_str();
unsigned int Act_len1 = 0;
for (unsigned int i = 0; i + 3 < Act_Message1.length(); i = i + 3)
{
sscanf_s(b + i, "%02X", (int *)(Response_Message + Act_len1));
Act_len1++;
}
sscanf_s(b + Act_Message1.length() - 2, "%02X", (int *)(Response_Message + Act_len1));

int test_Value = Analysis_Response_Message(Response_Message, Request_Message, Act_len1 + 1);

Assert::AreEqual(test_Value,Output);
}
}

void Test_Salve_Analysis_Request_Msg(void)
{
char buf[LEN];
char buf1[LEN];
CString name = "Example";
char s[10] = "";
int Input1, Output1, Output2;
int number = GetPrivateProfileInt(name, "Number", 0, TESTPATH3);
for (int i = 1; i < number + 1; i++)
{
memset(buf, 0, sizeof(buf));
memset(buf1, 0, sizeof(buf1));
memset(s, 0, sizeof(s));
_itoa_s(i, s, 10);
CString name1 = name + s;
Input1 = GetPrivateProfileString(name1, "Input1", "", buf, LEN, TESTPATH3);
Output1 = GetPrivateProfileString(name1, "Output1", "", buf1, LEN, TESTPATH3);
Output2 = GetPrivateProfileInt(name1, "Output2", 0, TESTPATH3);
//buf ÇëÇó buf1 ÏìÓ¦
UINT8 Request_Message[300];
string Act_Message = buf;
const char *a = Act_Message.c_str();
unsigned int Act_len = 0;
for (unsigned int i = 0; i + 3 < Act_Message.length(); i = i + 3)
{
sscanf_s(a + i, "%02X", (int *)(Request_Message + Act_len));
Act_len++;
}
sscanf_s(a + Act_Message.length() - 2, "%02X", (int *)(Request_Message + Act_len));


UINT8 Response_Message[300];
string Act_Message1 = buf1;
const char *b = Act_Message1.c_str();
unsigned int Act_len1 = 0;
for (unsigned int i = 0; i + 3 < Act_Message1.length(); i = i + 3)
{
sscanf_s(b + i, "%02X", (int *)(Response_Message + Act_len1));
Act_len1++;
}
sscanf_s(b + Act_Message1.length() - 2, "%02X", (int *)(Response_Message + Act_len1));

int test_Value = Analysis_Response_Msg(Request_Message, Response_Message, Act_len + 1);

Assert::AreEqual(test_Value, Output2);
}
}

void Test_Salve_Create_Response_Msg(void)
{
char buf[LEN];
char buf1[LEN];
CString name = "Example";
char s[10] = "";
int Input1, Output1, Output2;
bool test_Value = true;
int number = GetPrivateProfileInt(name, "Number", 0, TESTPATH3);
Init_Coil_Register();
for (int i = 1; i < number + 1; i++)
{
memset(buf, 0, sizeof(buf));
memset(buf1, 0, sizeof(buf1));
memset(s, 0, sizeof(s));
_itoa_s(i, s, 10);
CString name1 = name + s;
Input1 = GetPrivateProfileString(name1, "Input1", "", buf, LEN, TESTPATH3);
Output1 = GetPrivateProfileString(name1, "Output1", "", buf1, LEN, TESTPATH3);
Output2 = GetPrivateProfileInt(name1, "Output2", 0, TESTPATH3);
//buf ÇëÇó buf1 ÏìÓ¦
UINT8 Request_Message[600];
memset(Request_Message,0,600);
string Act_Message = buf;
const char *a = Act_Message.c_str();
unsigned int Act_len = 0;
int temp = 0;
for (unsigned int i = 0; i + 3 < Act_Message.length(); i = i + 3)
{
sscanf_s(a + i, "%02X", &temp);
Request_Message[Act_len] = temp;
Act_len++;
}
sscanf_s(a + Act_Message.length() - 2, "%02X", &temp);
Request_Message[Act_len] = temp;

UINT8 Response_Message[600];
memset(Response_Message, 0, 600);
string Act_Message1 = buf1;
const char *b = Act_Message1.c_str();
unsigned int Act_len1 = 0;
int temp1 = 0;
for (unsigned int i = 0; i + 3 < Act_Message1.length(); i = i + 3)
{
sscanf_s(b + i, "%02X", &temp1);
Response_Message[Act_len1] = temp1;
Act_len1++;
}
sscanf_s(b + Act_Message1.length() - 2, "%02X", &temp1);
Response_Message[Act_len1] = temp1;

UINT8 Response_Message1[600];
memset(Response_Message1,0,600);
int flage = Analysis_Response_Msg(Request_Message, Response_Message1, Act_len + 1);
Create_Response_Message(Request_Message, Response_Message1, flage);
for (unsigned int j = 0; j < Act_len1+1; j++)
{
if (Response_Message[j] != Response_Message1[j])
{
test_Value = false;
break;
}
}
Assert::AreEqual(test_Value, true);
}
}


+ 20
- 0
Modbus_communication/UnitTest_DLL/master_salve_test.h View File

@@ -0,0 +1,20 @@
#ifndef __MASTER_SALVE_TEST_H
#define __MASTER_SALVE_TEST_H

#include "CppUnitTest.h"
#include "../Master_Salve_DLL/Modbus.h"
#include <windows.h>
#include <atlstr.h>

#define TESTPATH1 "../testini/1.ini"
#define TESTPATH2 "../testini/2.ini"
#define TESTPATH3 "../testini/3.ini"
#define LEN 65535
using namespace Microsoft::VisualStudio::CppUnitTestFramework;

void Test_Master_Create_Request_Msg(void);
void Test_Master_Analysis_Response_Msg(void);
void Test_Salve_Analysis_Request_Msg(void);
void Test_Salve_Create_Response_Msg(void);

#endif

+ 30
- 0
Modbus_communication/UnitTest_DLL/unittest1.cpp View File

@@ -0,0 +1,30 @@
#include "CppUnitTest.h"
#include "master_salve_test.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace UnitTest_DLL
{
TEST_CLASS(UnitTest1)
{
public:
TEST_METHOD(TestMethod1)
{
Test_Master_Create_Request_Msg();
}

TEST_METHOD(TestMethod2)
{
Test_Master_Analysis_Response_Msg();
}
TEST_METHOD(TestMethod3)
{
Test_Salve_Analysis_Request_Msg();
}
TEST_METHOD(TestMethod4)
{
Test_Salve_Create_Response_Msg();
}
};
}

Modbus_communication/TCP_Master_test/1.ini → Modbus_communication/testini/1.ini View File


Modbus_communication/TCP_Master_test/2.ini → Modbus_communication/testini/2.ini View File

@@ -1,119 +1,188 @@
[Example]
Number = 27
Number = 33

;0x01正常读取响应解析样例
[Example1]
Input1 = "00 00 00 00 00 06 01 01 00 00 00 01"
Input2 = "00 00 00 00 00 04 01 01 01 00"
Output = 5

[Example2]
Input1 = "00 01 00 00 00 06 01 01 00 00 00 64"
Input2 = "00 01 00 00 00 10 01 01 0D 00 00 00 00 00 00 00 00 00 00 00 00 00"
Output = 5

[Example3]
Input1 = "00 03 00 00 00 06 01 01 00 00 07 D0"
Input2 = "00 03 00 00 00 FD 01 01 FA 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 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 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 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 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 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 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 00 00 00 00 00"
Output = 5

;0x03正常读取响应解析样例
[Example4]
Input1 = "00 06 00 00 00 06 01 03 00 00 00 01"
Input2 = "00 06 00 00 00 05 01 03 02 00 00"
Output = 5

[Example5]
Input1 = "00 00 00 00 00 06 01 03 00 00 00 02"
Input2 = "00 00 00 00 00 07 01 03 04 00 00 00 00"
Output = 5

[Example6]
Input1 = "00 07 00 00 00 06 01 03 00 0A 00 0A"
Input2 = "00 07 00 00 00 17 01 03 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"
Output = 5

[Example7]
Input1 = "00 08 00 00 00 06 01 03 00 00 00 7D"
Input2 = "00 08 00 00 00 FD 01 03 FA 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 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 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 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 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 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 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 00 00 00 00 00"
Output = 5

;0x0F正常写入响应解析样例
[Example8]
Input1 = "00 0A 00 00 00 08 01 0F 00 00 00 01 01 01"
Input2 = "00 0A 00 00 00 06 01 0F 00 00 00 01"
Output = 5

[Example9]
Input1 = "00 0B 00 00 00 14 01 0F 00 00 00 64 0D 00 00 00 00 00 00 00 00 00 00 00 00 00"
Input2 = "00 0B 00 00 00 06 01 0F 00 00 00 64"
Output = 5

[Example10]
Input1 = "00 0C 00 00 00 FD 01 0F 00 05 07 B0 F6 FF FF FF FF FF FF FF FF FF FF FF FF 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 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 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 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 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 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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"
Input2 = "00 0C 00 00 00 06 01 0F 00 05 07 B0"
Output = 5

;0x10正常写入响应解析样例
[Example11]
Input1 = "00 0E 00 00 00 09 01 10 00 00 00 01 02 11 11"
Input2 = "00 0E 00 00 00 06 01 10 00 00 00 01"
Output = 5

[Example12]
Input1 = "00 0F 00 00 00 11 01 10 00 0A 00 05 0A 00 11 22 33 44 55 66 77 88 99"
Input2 = "00 0F 00 00 00 06 01 10 00 0A 00 05"
Output = 5

[Example13]
Input1 = "00 10 00 00 00 FD 01 10 00 64 00 7B F6 FF FF FF FF FF FF FF FF FF FF FF FF 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 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 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 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 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 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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"
Input2 = "00 10 00 00 00 06 01 10 00 64 00 7B"
Output = 5

;异常响应样例
;MBAP报文头不对
[Example14]
Input1 = "00 0E 00 00 00 08 01 0F 00 00 00 01 01 01"
Input2 = "00 0F 00 00 00 06 01 0F 00 00 00 01"
Output = 1

[Example15]
Input1 = "00 0E 00 00 00 08 01 0F 00 00 00 01 01 01"
Input2 = "00 0E 01 00 00 06 01 0F 00 00 00 01"
Output = 1

[Example16]
Input1 = "00 0E 00 00 00 08 01 0F 00 00 00 01 01 01"
Input2 = "00 0E 00 1E 00 06 01 0F 00 00 00 01"
Output = 1

[Example17]
Input1 = "00 0E 00 00 00 08 01 0F 00 00 00 01 01 01"
Input2 = "00 0E 00 00 11 06 01 0F 00 00 00 01"
Output = 1


;后续字节长度不对
[Example18]
Input1 = "00 0E 00 00 00 06 01 01 00 00 00 01"
Input2 = "00 0E 00 00 00 03 01 01 01 00"
Output = 0

;设备ID不对
[Example19]
Input1 = "00 0E 00 00 00 06 01 01 00 00 00 01"
Input2 = "00 0E 00 00 00 04 02 01 01 00"
Output = 1

;功能码不对
[Example20]
Input1 = "00 0E 00 00 00 06 01 01 00 00 00 01"
Input2 = "00 0E 00 00 00 04 01 03 01 00"
Output = 2

;操作地址不对
[Example21]
Input1 = "00 0E 00 00 00 06 01 10 00 00 00 02 04 11 11 11 11"
Input2 = "00 0E 00 00 00 06 01 10 50 10 00 02"
Output = 3

;操作数量不对
[Example22]
Input1 = "00 0E 00 00 00 0B 01 10 00 00 00 02 04 11 11 11 11"
Input2 = "00 0E 00 00 00 06 01 10 00 00 01 02"
Output = 4

;数据字节数不对
[Example23]
Input1 = "00 0E 00 00 00 06 01 03 00 00 00 02"
Input2 = "00 0E 00 00 00 07 01 03 02 11 11 11 11"
Output = 0

;异常码响应样例
[Example24]
Input1 = "00 0E 00 00 00 06 01 03 00 00 00 02"
Input2 = "00 0E 00 00 00 03 01 83 01"
Output = 6

[Example25]
Input1 = "00 0E 00 00 00 06 01 01 00 00 00 02"
Input2 = "00 0E 00 00 00 03 01 81 02"
Output = 6

[Example26]
Input1 = "00 0E 00 00 00 08 01 0F 00 00 00 02 01 00"
Input2 = "00 0E 00 00 00 03 01 8F 03"
Output = 6

[Example27]
Input1 = "00 0E 00 00 00 09 01 10 00 00 00 01 02 00 00"
Input2 = "00 0E 00 00 00 03 01 90 04"
Output = 6

;异常码基础上 功能码不对
[Example28]
Input1 = "00 0E 00 00 00 09 01 10 00 00 00 01 02 00 00"
Input2 = "00 0E 00 00 00 03 01 83 04"
Output = 2

[Example29]
Input1 = "00 0E 00 00 00 06 01 01 00 00 00 01"
Input2 = "00 0E 00 00 00 03 01"
Output = 0

[Example30]
Input1 = "00 0E 00 00 00 06 01 01 00 00 00 01"
Input2 = "00 0E 00 00 00 04 01 81 00 00"
Output = 0

[Example31]
Input1 = "00 0E 00 00 00 06 01 10 00 00 00 00"
Input2 = "00 0E 00 00 00 03 01 90 03"
Output = 6

[Example32]
Input1 = "00 0E 00 00 00 06 01 10 00 00 00 01 02 11 11"
Input2 = "00 0E 00 00 00 07 01 10 00 00 00 01 00"
Output = 0

[Example33]
Input1 = "00 0E 00 00 00 06 01 03 00 00 00 01"
Input2 = "00 0E 00 00 00 06 01 03 03 00 00 00"
Output = 0







Modbus_communication/RTU_Salve_test/3.ini → Modbus_communication/testini/3.ini View File

@@ -1,195 +1,252 @@
[Example]
Number = 41
Number = 44

;0x01功能码正常读取响应
[Example1]
Input1 = "09 01 00 00 00 01 FC 82"
Output = "09 01 01 01 92 28"
Output1 = "09 01 01 01 92 28"
Output2 = 1

[Example2]
Input1 = "09 01 00 00 00 0A BD 45"
Output = "09 01 02 FF 03 59 CC"
Output1 = "09 01 02 FF 03 59 CC"
Output2 = 1

[Example3]
Input1 = "09 01 00 00 00 C8 3C D4"
Output = "09 01 19 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF D6 40"
Output1 = "09 01 19 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF D6 40"
Output2 = 1

[Example4]
Input1 = "09 01 00 00 07 D0 3E EE"
Output = "09 01 FA FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 8D BF"
Output1 = "09 01 FA FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 8D BF"
Output2 = 1

;0x01功能码下03异常码响应
[Example5]
Input1 = "09 01 00 00 07 D1 FF 2E"
Output = "09 81 03 81 93"
Output1 = "09 81 03 81 93"
Output2 = 3

[Example6]
Input1 = "09 01 00 00 00 00 3D 42"
Output = "09 81 03 81 93"
Output1 = "09 81 03 81 93"
Output2 = 3

[Example7]
Input1 = "09 01 00 00 00 01 00 82 41"
Output = "09 81 03 81 93"
Output1 = "09 81 03 81 93"
Output2 = 3

;0x01功能码下无响应
[Example8]
Input1 = "09 01 00 00 00 01 11 11"
Output = ""
Output1 = ""
Output2 = 0

[Example9]
Input1 = "08 01 00 00 00 01 FD 53"
Output = ""
Output1 = ""
Output2 = 0

;0x01功能码下02异常码
[Example10]
Input1 = "09 01 27 06 00 14 D7 F8"
Output = "09 81 02 40 53"
Output1 = "09 81 02 40 53"
Output2 = 1


;0x03功能码正常读取响应样例
[Example11]
Input1 = "09 03 00 00 00 01 85 42"
Output = "09 03 02 FF FF 58 35"
Output1 = "09 03 02 FF FF 58 35"
Output2 = 1

[Example12]
Input1 = "09 03 00 00 00 64 45 69"
Output = "09 03 C8 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ED 8C"
Output1 = "09 03 C8 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ED 8C"
Output2 = 1

[Example13]
Input1 = "09 03 00 00 00 7B 04 A1"
Output = "09 03 F6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 34 54"
Output1 = "09 03 F6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 34 54"
Output2 = 1

[Example14]
Input1 = "09 03 00 00 00 7D 84 A3"
Output = "09 03 FA FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 70 F8"
Output1 = "09 03 FA FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 70 F8"
Output2 = 1

;0x03功能码下03异常码响应
[Example15]
Input1 = "09 03 00 00 00 00 44 82"
Output = "09 83 03 80 F3"
Output1 = "09 83 03 80 F3"
Output2 = 3

[Example16]
Input1 = "09 03 00 00 00 7E C4 A2"
Output = "09 83 03 80 F3"
Output1 = "09 83 03 80 F3"
Output2 = 3

[Example17]
Input1 = "09 03 00 00 00 01 00 83 A3"
Output = "09 83 03 80 F3"
Output1 = "09 83 03 80 F3"
Output2 = 3

;0x03功能码下无响应
[Example18]
Input1 = "09 03 00 00 00 01 11 11"
Output = ""
Output1 = ""
Output2 = 0

[Example19]
Input1 = "08 03 00 00 00 01 84 93"
Output = ""
Output1 = ""
Output2 = 0

;0x03功能码下02异常码
[Example20]
Input1 = "09 03 27 06 00 14 AE 38"
Output = "09 83 02 41 33"



Output1 = "09 83 02 41 33"
Output2 = 1



;0x0F正常写入样例
[Example21]
Input1 = "09 0F 00 00 00 01 01 01 EE F1"
Output = "09 0F 00 00 00 01 95 43"
Output1 = "09 0F 00 00 00 01 95 43"
Output2 = 1


[Example22]
Input1 = "09 0F 00 00 07 B0 F6 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 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 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 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 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 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 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 00 B8 78"
Output = "09 0F 00 00 07 B0 57 07"
Output1 = "09 0F 00 00 07 B0 57 07"
Output2 = 1

;0x0F下03异常码样例
[Example23]
Input1 = "09 0F 00 00 00 00 54 83"
Output = "09 8F 03 85 F3"
Output1 = "09 8F 03 85 F3"
Output2 = 3

[Example24]
Input1 = "09 0F 00 00 00 01 01 01 00 71 4C"
Output = "09 8F 03 85 F3"
Output1 = "09 8F 03 85 F3"
Output2 = 3

[Example25]
Input1 = "09 0F 00 00 07 B1 F6 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 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 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 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 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 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 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 00 00 20 DB"
Output = "09 8F 03 85 F3"
Output1 = "09 8F 03 85 F3"
Output2 = 3

;0x0F下无响应
[Example26]
Input1 = "09 0F 00 00 00 01 01 01 11 F1"
Output = ""
Output1 = ""
Output2 = 0

[Example27]
Input1 = "08 0F 00 00 00 01 01 01 2F 3D"
Output = ""
Output1 = ""
Output2 = 0

;0x0F下02异常码
[Example28]
Input1 = "09 0F 27 06 00 14 03 02 FF FF 54 11"
Output = "09 8F 02 44 33"
Output1 = "09 8F 02 44 33"
Output2 = 1



;0x10下正常写入响应样例
[Example29]
Input1 = "09 10 00 00 00 01 02 00 00 C1 90"
Output = "09 10 00 00 00 01 00 81"
Output1 = "09 10 00 00 00 01 00 81"
Output2 = 1

[Example30]
Input1 = "09 10 00 00 00 02 04 00 00 00 00 D9 CF"
Output = "09 10 00 00 00 02 40 80"
Output1 = "09 10 00 00 00 02 40 80"
Output2 = 1

[Example31]
Input1 = "09 10 00 00 00 7B F6 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 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 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 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 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 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 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 00 CE 42"
Output = "09 10 00 00 00 7B 81 62"
Output1 = "09 10 00 00 00 7B 81 62"
Output2 = 1

;0x10下03异常码
[Example32]
Input1 = "09 10 00 00 00 00 C1 41"
Output = "09 90 03 8D C3"
Output1 = "09 90 03 8D C3"
Output2 = 3

[Example33]
Input1 = "09 10 00 00 00 01 02 00 00 00 51 90"
Output = "09 90 03 8D C3"
Output1 = "09 90 03 8D C3"
Output2 = 3

;0x10下无响应
[Example34]
Input1 = "09 10 00 00 00 01 02 01 01 11 11"
Output = ""
Output1 = ""
Output2 = 0

[Example35]
Input1 = "08 10 00 00 00 01 02 01 01 0C 50"
Output = ""
Output1 = ""
Output2 = 0

;0x10下02异常码
[Example36]
Input1 = "09 10 27 0F 00 02 04 00 00 00 00 26 7E"
Output = "09 90 02 4C 03"
Output1 = "09 90 02 4C 03"
Output2 = 1

[Example37]
Input1 = "09 10 27 06 00 14 28 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 00 00 00 00 00 D9 BB"
Output = "09 90 02 4C 03"
Output1 = "09 90 02 4C 03"
Output2 = 1

;其他特殊样例
;设备ID+功能码+CRC
[Example38]
Input1 = "09 01 C6 20"
Output = ""
Output1 = ""
Output2 = 0
;只有设备ID+CRC
[Example39]
Input1 = "09 7F 46"
Output = ""
Output1 = ""
Output2 = 0
;只有设备ID
[Example40]
Input1 = "09"
Output = ""
Output1 = ""
Output2 = 0
;01异常码
[Example41]
Input1 = "09 02 00 00 00 01 B8 82"
Output = "09 82 01 00 A2"
Output1 = "09 82 01 00 A2"
Output2 = 2

[Example42]
Input1 = "09 0F 00 00 07 B1 F7 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 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 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 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 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 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 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 00 00 BD 42"
Output1 = "09 8F 03 85 F3"
Output2 = 3

[Example43]
Input1 = "09 10 00 00 00 00 C1 41"
Output1 ="09 90 03 8D C3"
Output2 = 3

[Example44]
Input1 = "09 10 00 00 00 7C F8 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 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 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 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 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 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 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 00 00 00 93 49"
Output1 = "09 90 03 8D C3"
Output2 = 3







Loading…
Cancel
Save