diff --git a/Modbus_communication/Modbus_RTU_Salve/RTU_Salve.cpp b/Modbus_communication/Modbus_RTU_Salve/RTU_Salve.cpp index 2188b48..41b2b31 100644 --- a/Modbus_communication/Modbus_RTU_Salve/RTU_Salve.cpp +++ b/Modbus_communication/Modbus_RTU_Salve/RTU_Salve.cpp @@ -5,54 +5,191 @@ char read_buf[MAX_NUMBER]; bitset Coil_date; //0-9999 UINT16 Register[MAX_Address]; // 0-9999 + /********************************************************************************************* -* 功能     :  生成正常响应报文 -* 描述    : 经过校验后请求报文可以正常响应 -* 输入 : *Requst_Message 请求报文 *Normal_Response_Message 正常响应报文 -* 返回值 : 无 +* 功能     :  Bitset转UINT8类型 +* 描述    : Bitset ==》UINT8 +* 输入 : Bitset_Address Bitset的起始地址 Read_Number 要读取的位数 +* 返回值 : Date 转换后的UNIT8数据 **********************************************************************************************/ -void Create_Normal_Response_Message(UINT8 *Requst_Message, UINT8 *Normal_Response_Message) +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 (int i = 0; i < 8; i++) + { + Date = Date << 1 | (int)Coil_date[len--]; + } + } + else + { + unsigned int len = Bitset_Address + Read_Number-1; + for (int i = 0; i < Read_Number; i++) + { + Date = Date << 1 | (int)Coil_date[len--]; + } + } + return Date; +} - +/********************************************************************************************* +* 功能     :  生成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[0], 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+2; //响应报文中的后续字节数 + } + else //地址超限 + { + Response_Message[0] = Device_ID; + Response_Message[1] = Requst_Message[1] + 0x80; + Response_Message[2] = 0x02; + } } /********************************************************************************************* -* 功能     :  生成异常响应报文 -* 描述    : 经过校验后请求报文可以正常响应 -* 输入 : *Requst_Message 请求报文 *Normal_Response_Message 异常响应报文 +* 功能     :  生成0x03功能码响应报文 +* 描述    : 通过判断地址范围生成0x03对应的响应报文 +* 输入 : *Requst_Message 请求报文 *Response_Message响应报文 * 返回值 : 无 **********************************************************************************************/ -void Create_Abnormal_Response_Message(UINT8 *Requst_Message, UINT8 *Abnormal_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[0], 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 + 2; //响应报文中的后续字节数 + } + else //地址超限 + { + Response_Message[0] = Device_ID; + Response_Message[1] = Requst_Message[1] + 0x80; + Response_Message[2] = 0x02; + } } - -void Create_0x01_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, unsigned int Address_range) +/********************************************************************************************* +* 功能     :  写入线圈 +* 描述    : 将数据写入线圈中 +* 输入 : Write_date_Message 要写入的数据 Write_Number要写入的位数 Start_Address起始地址 +* 返回值 : 无 +**********************************************************************************************/ +void Write_Coil_date(UINT8 Write_date_Message, unsigned int Write_Number, unsigned int Start_Address) { - if (Address_range > MAX_Address) + if (Write_Number >= 8) { - int Read_Number = Requst_Message[4] << 8 | Requst_Message[5]; - + for (unsigned int i = Start_Address; i < Start_Address+8; i++) + { + Coil_date[i] = Write_date_Message & 1; + 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 >> 1; + } } } -void Create_0x03_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, unsigned int Address_range) -{ -} -void Create_0x0F_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, unsigned int Address_range) +/********************************************************************************************* +* 功能     :  生成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 (unsigned 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]; + } + else //地址超限 + { + Response_Message[0] = Device_ID; + Response_Message[1] = Requst_Message[1] + 0x80; + Response_Message[2] = 0x02; + } } -void Create_0x10_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, unsigned int Address_range) -{ +/********************************************************************************************* +* 功能     :  生成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 (unsigned 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]; + } + else //地址超限 + { + Response_Message[0] = Device_ID; + Response_Message[1] = Requst_Message[1] + 0x80; + Response_Message[2] = 0x02; + } } @@ -67,13 +204,13 @@ bool Create_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message) { if (Requst_Message[0] != Device_ID) //检查设备ID一致 return false; - unsigned int Address_range = (Requst_Message[2] << 8 | Requst_Message[3]) + (Requst_Message[4] << 8 | Requst_Message[5]); + switch (Requst_Message[1]) { - case 0x01:Create_0x01_Response_Message(Requst_Message, Response_Message, Address_range); break; - case 0x03:Create_0x03_Response_Message(Requst_Message, Response_Message, Address_range); break; - case 0x0F:Create_0x0F_Response_Message(Requst_Message, Response_Message, Address_range); break; - case 0x10:Create_0x10_Response_Message(Requst_Message, Response_Message, Address_range); break; + 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: } return true; diff --git a/Modbus_communication/Modbus_RTU_Salve/common.cpp b/Modbus_communication/Modbus_RTU_Salve/common.cpp index 8963703..0699907 100644 --- a/Modbus_communication/Modbus_RTU_Salve/common.cpp +++ b/Modbus_communication/Modbus_RTU_Salve/common.cpp @@ -303,5 +303,26 @@ BYTE Input_Parity(void) } +/********************************************************************************************* +* 功能    : 计算写入数据的字节数 +* 描述   : 通过对应的功能码和操作数量计算对应的数据字节数 +* 输入 : Function_code 选择的功能码类型 Operations_Number对应功能码类型的操作数量 +* 输出 : Write_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) //读线圈 + { + Read_date_number = Operations_Number / 8; + if (Operations_Number % 8) + Read_date_number++; + } + if (Function_code == 0x03) + Read_date_number = Operations_Number * 2; + return Read_date_number; +} + + diff --git a/Modbus_communication/Modbus_RTU_Salve/common.h b/Modbus_communication/Modbus_RTU_Salve/common.h index 2a76c61..3443844 100644 --- a/Modbus_communication/Modbus_RTU_Salve/common.h +++ b/Modbus_communication/Modbus_RTU_Salve/common.h @@ -8,5 +8,6 @@ using namespace std; #define MAX_NUMBER 300 +unsigned int Count_Read_date_number(int Function_code, unsigned int Operations_Number); #endif \ No newline at end of file