|
- #include "RTU_Salve.h"
- #include <bitset>
- char read_buf[MAX_NUMBER];
-
- bitset<MAX_Address> 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;
- }
|