From 984e09fe2444b69285b9cd9418d10bf36a9c4bc7 Mon Sep 17 00:00:00 2001 From: zcn1123 <2363211205@qq.com> Date: Thu, 3 Sep 2020 10:44:35 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B4=E5=90=88=E9=83=A8=E5=88=86=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Modbus_RTU_Salve/RTU_Salve.cpp | 114 ++++++++++++------ .../Modbus_RTU_Salve/RTU_Salve.h | 2 + .../Modbus_RTU_Salve/common.cpp | 8 +- .../Modbus_RTU_Salve/main.cpp | 2 +- 4 files changed, 86 insertions(+), 40 deletions(-) diff --git a/Modbus_communication/Modbus_RTU_Salve/RTU_Salve.cpp b/Modbus_communication/Modbus_RTU_Salve/RTU_Salve.cpp index 942da9d..d4ab135 100644 --- a/Modbus_communication/Modbus_RTU_Salve/RTU_Salve.cpp +++ b/Modbus_communication/Modbus_RTU_Salve/RTU_Salve.cpp @@ -4,6 +4,7 @@ char read_buf[MAX_NUMBER]; bitset Coil_date; //0-9999 UINT16 Register[MAX_Address]; // 0-9999 +unsigned int Response_Message_Len; /********************************************************************************************* * 功能     :  初始化线圈和寄存器 @@ -32,7 +33,7 @@ UINT8 Bitset_to_Uint8(unsigned int Bitset_Address, unsigned int Read_Number) if (Read_Number >= 8) { unsigned int len = Bitset_Address + 8; - for (int i = 0; i < 8; i++) + for (unsigned int i = 0; i < 8; i++) { Date = Date << 1 | (int)Coil_date[len--]; } @@ -40,7 +41,7 @@ UINT8 Bitset_to_Uint8(unsigned int Bitset_Address, unsigned int Read_Number) else { unsigned int len = Bitset_Address + Read_Number-1; - for (int i = 0; i < Read_Number; i++) + for (unsigned int i = 0; i < Read_Number; i++) { Date = Date << 1 | (int)Coil_date[len--]; } @@ -70,13 +71,21 @@ void Create_0x01_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message } Response_Message[0] = Device_ID; Response_Message[1] = Requst_Message[1]; - Response_Message[2] = Read_Len+2; //响应报文中的后续字节数 + 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 //地址超限 + else { Response_Message[0] = Device_ID; Response_Message[1] = Requst_Message[1] + 0x80; - Response_Message[2] = 0x02; + Response_Message[2] = 0x02;//地址超限异常码02 + 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; } } @@ -102,13 +111,21 @@ void Create_0x03_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message } Response_Message[0] = Device_ID; Response_Message[1] = Requst_Message[1]; - Response_Message[2] = Read_Len + 2; //响应报文中的后续字节数 + 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 //地址超限 { Response_Message[0] = Device_ID; Response_Message[1] = Requst_Message[1] + 0x80; Response_Message[2] = 0x02; + 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; } } @@ -125,7 +142,7 @@ void Write_Coil_date(UINT8 Write_date_Message, unsigned int Write_Number, unsign for (unsigned int i = Start_Address; i < Start_Address+8; i++) { Coil_date[i] = Write_date_Message & 1; - Write_date_Message >> 1; + Write_date_Message = Write_date_Message >> 1; } } else @@ -133,7 +150,7 @@ void Write_Coil_date(UINT8 Write_date_Message, unsigned int Write_Number, unsign for (unsigned int i = Start_Address; i < Start_Address + Write_Number; i++) { Coil_date[i] = Write_date_Message & 1; - Write_date_Message >> 1; + Write_date_Message = Write_date_Message >> 1; } } } @@ -151,7 +168,7 @@ void Create_0x0F_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message 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++)//执行写入线圈操作 + for (int i = 7; i < Requst_Message[6]+7; i++)//执行写入线圈操作 { Write_Coil_date(Requst_Message[i], Write_Number, Start_Address); Write_Number -= 8; @@ -163,12 +180,21 @@ void Create_0x0F_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message 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 //地址超限 { Response_Message[0] = Device_ID; Response_Message[1] = Requst_Message[1] + 0x80; Response_Message[2] = 0x02; + 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; } } @@ -185,7 +211,7 @@ void Create_0x10_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message 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)//执行写入寄存器操作 + 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++; @@ -196,12 +222,20 @@ void Create_0x10_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message 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 //地址超限 { Response_Message[0] = Device_ID; Response_Message[1] = Requst_Message[1] + 0x80; Response_Message[2] = 0x02; + 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; } } @@ -224,11 +258,21 @@ void Create_Abnormal_Function_Code_Response_Message(UINT8 *Requst_Message, UINT8 * 返回值 : true 生成响应报文 * false 不生成响应报文 **********************************************************************************************/ -bool Create_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message) + +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; +} +bool Create_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, DWORD Read_len) { + if (!Check_Requst_Message_CRC(Requst_Message, Read_len))//CRC校验报文是否正确 + return false; if (Requst_Message[0] != Device_ID) //检查设备ID一致 return false; - switch (Requst_Message[1]) { case 0x01:Create_0x01_Response_Message(Requst_Message, Response_Message); break; @@ -242,44 +286,42 @@ bool Create_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message) -int test(void) +int Modbus_RTU_Salve(void) { - string COMM; - cin >> COMM; - HANDLE Handle_Com = Init_COM((LPCTSTR)COMM.c_str(), 9600, 8, 0, 1); + 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; } - - char write_buf[MAX_NUMBER]; - memset(write_buf, 0, MAX_NUMBER); - DWORD dwRead; + Init_Coil_Register(); + DWORD Read_len; while (true) { - //RTU主站,生成并发送请求,计时,读取响应报文,先发送后接收 - //生成请求报文 - //发送请求报文 - PurgeComm(Handle_Com, PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT);//清除缓存 - while (1) + BOOL Read_flage = ReadFile(Handle_Com, Requst_Message, 256, &Read_len, NULL); //阻塞等待接收请求报文 + if (Read_flage && (Read_len > 0)) { - if (true == SendData(Handle_Com, "ok", 2)) + if (Create_Response_Message(Requst_Message, Response_Message, Read_len)) { - cout << "发送请求报文成功" << endl; - break; + while (SendData(Handle_Com, (char*)Response_Message, Response_Message_Len)) + { + printf("发送失败,重新发送"); + } } + else + continue; } - BOOL bReadOK = ReadFile(Handle_Com, read_buf, 256, &dwRead, NULL); - if (bReadOK && (dwRead > 0)) - { - read_buf[dwRead] = '\0'; - printf("收到响应:%s \r\n", read_buf); - } - else - cout << "loss" << endl; + } CloseHandle(Handle_Com); getchar(); diff --git a/Modbus_communication/Modbus_RTU_Salve/RTU_Salve.h b/Modbus_communication/Modbus_RTU_Salve/RTU_Salve.h index c3314e0..0915441 100644 --- a/Modbus_communication/Modbus_RTU_Salve/RTU_Salve.h +++ b/Modbus_communication/Modbus_RTU_Salve/RTU_Salve.h @@ -6,4 +6,6 @@ #define MAX_Address 9999 #define MAX_NUMBER 256 +int Modbus_RTU_Salve(void); + #endif \ No newline at end of file diff --git a/Modbus_communication/Modbus_RTU_Salve/common.cpp b/Modbus_communication/Modbus_RTU_Salve/common.cpp index bca07f6..e23a5bb 100644 --- a/Modbus_communication/Modbus_RTU_Salve/common.cpp +++ b/Modbus_communication/Modbus_RTU_Salve/common.cpp @@ -47,7 +47,7 @@ HANDLE Init_COM(LPCTSTR Port, int baud_rate, BYTE date_bits, BYTE stop_bit, BYTE COMMTIMEOUTS CommTimeOuts; GetCommTimeouts(Handle_Com, &CommTimeOuts); CommTimeOuts.ReadIntervalTimeout = 5; - CommTimeOuts.ReadTotalTimeoutMultiplier = 1; + CommTimeOuts.ReadTotalTimeoutMultiplier = 0; CommTimeOuts.ReadTotalTimeoutConstant = 0; CommTimeOuts.WriteTotalTimeoutMultiplier = 10; CommTimeOuts.WriteTotalTimeoutConstant = 1000; @@ -121,7 +121,7 @@ bool Check_Input_COMM(string Comm) string compare2 = "COM"; for (unsigned int i = 0; i < 3; i++) { - if (Comm[i] != compare1[i] || Comm[i] != compare2[i]) + if (Comm[i] != compare1[i] && Comm[i] != compare2[i]) return false; } if (Comm[3] == 0x30) @@ -215,6 +215,7 @@ BYTE Input_Date_Bits(void) printf("支持的数据位有:5,6,7,8 \n"); do { + cin >> hex; if (flage == 1) { printf("请输入有效数据位:"); @@ -223,6 +224,7 @@ BYTE Input_Date_Bits(void) else printf("请重新输入有效数据位:"); cin >> Date_Bits; + } while (!(Date_Bits == 5 || Date_Bits == 6 || Date_Bits == 7 || Date_Bits == 8)); return Date_Bits; } @@ -318,7 +320,7 @@ unsigned int Count_Read_date_number(int Function_code, unsigned int Operations_N if (Operations_Number % 8) Read_date_number++; } - if (Function_code == 0x03) + if (Function_code == 0x03)//读寄存器 Read_date_number = Operations_Number * 2; return Read_date_number; } diff --git a/Modbus_communication/Modbus_RTU_Salve/main.cpp b/Modbus_communication/Modbus_RTU_Salve/main.cpp index 294c7c4..eb9e6ad 100644 --- a/Modbus_communication/Modbus_RTU_Salve/main.cpp +++ b/Modbus_communication/Modbus_RTU_Salve/main.cpp @@ -2,7 +2,7 @@ int main() { - test(); + Modbus_RTU_Salve(); getchar(); return 0; } \ No newline at end of file