#include "RTU_Salve.h" #include char read_buf[MAX_NUMBER]; bitset Coil_date; //0-9999 UINT16 Register[MAX_Address]; // 0-9999 unsigned int Response_Message_Len; /********************************************************************************************* * 功能     :  初始化线圈和寄存器 * 描述    : 对线圈和寄存器数组赋值为全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 + 8; for (unsigned int i = 0; i < 8; i++) { Date = Date << 1 | (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 | (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)//判断地址是否超限 { unsigned int Write_Number = Requst_Message[4] << 8 | Requst_Message[5];//要写入的寄存器个数 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) + 9; if (Read_len != Count_len) 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 < 2 || Operation_Number > 1968) return false; } if (Requst_Message[1] == 0x10) { if (Operation_Number < 2 || Operation_Number > 123) return false; } return true; } /********************************************************************************************* * 功能     :  生成响应报文 * 描述    : 检查设备请求报文来生成对应功能的响应报文 * 输入 : *Requst_Message 请求报文 *Response_Message响应报文 * 返回值 : true 生成响应报文 * false 不生成响应报文 **********************************************************************************************/ bool Create_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, DWORD Read_len) { if (Requst_Message[0] != Device_ID) //检查设备ID一致 return false; if (!Check_Requst_Message_CRC(Requst_Message, Read_len))//CRC校验报文是否正确 return false; 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; } 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); } return true; } int Modbus_RTU_Salve(void) { string COMM = Input_COMM(); unsigned int Baud_Rate = Input_Baud_Rate(); BYTE Date_Bits = Input_Date_Bits(); BYTE Stop_Bits = Input_Stop_Bits(Date_Bits); BYTE Parity = Input_Parity(); UINT8 Requst_Message[MAX_NUMBER]; UINT8 Response_Message[MAX_NUMBER]; HANDLE Handle_Com = Init_COM((LPCTSTR)COMM.c_str(), Baud_Rate, Date_Bits, Stop_Bits, Parity); if (Handle_Com == INVALID_HANDLE_VALUE) { cout << "初始化串口失败" << endl; getchar(); return 0; } else printf("初始化串口成功"); Init_Coil_Register(); DWORD Read_len; while (true) { PurgeComm(Handle_Com, PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT);//清除缓存 BOOL Read_flage = ReadFile(Handle_Com, Requst_Message, 256, &Read_len, NULL); //阻塞等待接收请求报文 if (Read_flage && (Read_len > 0)) { if (Create_Response_Message(Requst_Message, Response_Message, Read_len)) { while (!SendData(Handle_Com, (char*)Response_Message, Response_Message_Len)) { printf("发送失败,重新发送"); } Log_Note(Requst_Message, 0, Read_len); Log_Note(Response_Message, 1, Response_Message_Len); } else continue; } } CloseHandle(Handle_Com); getchar(); return 0; }