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