|
- #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);
-
- }
|