|
|
@@ -4,6 +4,7 @@ char read_buf[MAX_NUMBER]; |
|
|
|
|
|
|
|
bitset<MAX_Address> 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--]; |
|
|
|
} |
|
|
@@ -48,6 +49,24 @@ UINT8 Bitset_to_Uint8(unsigned int Bitset_Address, unsigned int Read_Number) |
|
|
|
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对应的响应报文 |
|
|
@@ -61,7 +80,7 @@ void Create_0x01_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message |
|
|
|
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); //要读取的字节数 |
|
|
|
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); |
|
|
@@ -70,13 +89,15 @@ 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; |
|
|
|
Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message,0x02); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -93,7 +114,8 @@ void Create_0x03_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message |
|
|
|
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); //要读取的字节数 |
|
|
|
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; |
|
|
@@ -102,13 +124,15 @@ 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; |
|
|
|
Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x02); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -125,7 +149,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 +157,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 +175,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 +187,15 @@ 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; |
|
|
|
Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x02); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -185,7 +212,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,26 +223,89 @@ 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; |
|
|
|
Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x02); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/********************************************************************************************* |
|
|
|
* 功能 : 生成异常功能码响应报文 |
|
|
|
* 描述 : 对不支持的功能码生成对应的异常响应报文 |
|
|
|
* 输入 : *Requst_Message 请求报文 *Response_Message响应报文 |
|
|
|
* 返回值 : 无 |
|
|
|
* 功能 : CRC校验 |
|
|
|
* 描述 : 对请求报文中的数据进行CRC校验 |
|
|
|
* 输入 : *Requst_Message 请求报文 Read_len 接收到到的字节数 |
|
|
|
* 返回值 : true CRC校验通过 |
|
|
|
* false CRC校验不通过 |
|
|
|
**********************************************************************************************/ |
|
|
|
void Create_Abnormal_Function_Code_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message) |
|
|
|
bool Check_Requst_Message_CRC(UINT8 *Requst_Message, DWORD Read_len) |
|
|
|
{ |
|
|
|
Response_Message[0] = Device_ID; |
|
|
|
Response_Message[1] = Requst_Message[1] + 0x80; |
|
|
|
Response_Message[2] = 0x01; |
|
|
|
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; |
|
|
|
} |
|
|
|
/********************************************************************************************* |
|
|
|
* 功能 : 生成响应报文 |
|
|
@@ -224,62 +314,69 @@ void Create_Abnormal_Function_Code_Response_Message(UINT8 *Requst_Message, UINT8 |
|
|
|
* 返回值 : true 生成响应报文 |
|
|
|
* false 不生成响应报文 |
|
|
|
**********************************************************************************************/ |
|
|
|
bool Create_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message) |
|
|
|
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_Function_Code_Response_Message(Requst_Message, Response_Message); |
|
|
|
default: Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message,0x01); |
|
|
|
} |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
else |
|
|
|
printf("初始化串口成功"); |
|
|
|
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("发送失败,重新发送"); |
|
|
|
} |
|
|
|
Log_Note(Requst_Message, 0, Read_len); |
|
|
|
Log_Note(Response_Message, 1, Response_Message_Len); |
|
|
|
} |
|
|
|
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(); |
|
|
|