You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

385 lines
15 KiB

  1. #include "RTU_Salve.h"
  2. #include <bitset>
  3. char read_buf[MAX_NUMBER];
  4. bitset<MAX_Address> Coil_date; //0-9999
  5. UINT16 Register[MAX_Address]; // 0-9999
  6. unsigned int Response_Message_Len;
  7. /*********************************************************************************************
  8. * 功能     :  初始化线圈和寄存器
  9. * 描述    : 对线圈和寄存器数组赋值为全1
  10. * 输入 : 无
  11. * 返回值 : 无
  12. **********************************************************************************************/
  13. void Init_Coil_Register(void)
  14. {
  15. for (int i = 0; i < MAX_Address; i++)
  16. {
  17. Coil_date[i] = 1;
  18. Register[i] = 0xFFFF;
  19. }
  20. }
  21. /*********************************************************************************************
  22. * 功能     :  Bitset转UINT8类型
  23. * 描述    : Bitset ==》UINT8
  24. * 输入 : Bitset_Address Bitset的起始地址 Read_Number 要读取的位数
  25. * 返回值 : Date 转换后的UNIT8数据
  26. **********************************************************************************************/
  27. UINT8 Bitset_to_Uint8(unsigned int Bitset_Address, unsigned int Read_Number)
  28. {
  29. UINT8 Date = 0x00;
  30. if (Read_Number >= 8)
  31. {
  32. unsigned int len = Bitset_Address + 8;
  33. for (unsigned int i = 0; i < 8; i++)
  34. {
  35. Date = Date << 1 | (int)Coil_date[len--];
  36. }
  37. }
  38. else
  39. {
  40. unsigned int len = Bitset_Address + Read_Number-1;
  41. for (unsigned int i = 0; i < Read_Number; i++)
  42. {
  43. Date = Date << 1 | (int)Coil_date[len--];
  44. }
  45. }
  46. return Date;
  47. }
  48. /*********************************************************************************************
  49. * 功能     :  生成异常码响应报文
  50. * 描述    : 对不支持的功能码生成对应的异常响应报文
  51. * 输入 : *Requst_Message 请求报文 *Response_Message响应报文
  52. * 返回值 : 无
  53. **********************************************************************************************/
  54. void Create_Abnormal_Code_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, UINT8 Abnormal_Code)
  55. {
  56. Response_Message[0] = Device_ID;
  57. Response_Message[1] = Requst_Message[1] + 0x80;
  58. Response_Message[2] = Abnormal_Code;
  59. Response_Message_Len = 3;
  60. UINT16 CRC_date = CRC_16(Response_Message, 3);
  61. Response_Message[3] = CRC_date >> 8;//CRC_H
  62. Response_Message[4] = (UINT8)CRC_date; //CRC_L
  63. Response_Message_Len = 5;
  64. }
  65. /*********************************************************************************************
  66. * 功能     :  生成0x01功能码响应报文
  67. * 描述    : 通过判断地址范围生成0x01对应的响应报文
  68. * 输入 : *Requst_Message 请求报文 *Response_Message响应报文
  69. * 返回值 : 无
  70. **********************************************************************************************/
  71. void Create_0x01_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message)
  72. {
  73. unsigned int Start_Address = Requst_Message[2] << 8 | Requst_Message[3];
  74. unsigned int Address_range = Start_Address + (Requst_Message[4] << 8 | Requst_Message[5]);
  75. if (Address_range < MAX_Address)//判断地址是否超限
  76. {
  77. unsigned int Read_Number = Requst_Message[4] << 8 | Requst_Message[5];//要读取的位数
  78. unsigned int Read_Len = Count_Read_date_number(Requst_Message[1], Read_Number); //要读取的字节数
  79. for (unsigned int i = 3; i < Read_Len + 3; i++)
  80. {
  81. Response_Message[i] = Bitset_to_Uint8(Start_Address, Read_Number);
  82. Start_Address += 8;
  83. Read_Number -= 8;
  84. }
  85. Response_Message[0] = Device_ID;
  86. Response_Message[1] = Requst_Message[1];
  87. Response_Message[2] = Read_Len; //响应报文中的后续字节数
  88. UINT16 CRC_date = CRC_16(Response_Message, Read_Len+3);
  89. Response_Message_Len = Read_Len + 2 + 3;
  90. Response_Message[Response_Message_Len - 2] = CRC_date>>8;//CRC_H
  91. Response_Message[Response_Message_Len - 1] = (UINT8)CRC_date; //CRC_L
  92. }
  93. else
  94. {
  95. Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message,0x02);
  96. }
  97. }
  98. /*********************************************************************************************
  99. * 功能     :  生成0x03功能码响应报文
  100. * 描述    : 通过判断地址范围生成0x03对应的响应报文
  101. * 输入 : *Requst_Message 请求报文 *Response_Message响应报文
  102. * 返回值 : 无
  103. **********************************************************************************************/
  104. void Create_0x03_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message)
  105. {
  106. unsigned int Start_Address = Requst_Message[2] << 8 | Requst_Message[3];
  107. unsigned int Address_range = Start_Address + (Requst_Message[4] << 8 | Requst_Message[5]);
  108. if (Address_range < MAX_Address) //判断地址是否超限
  109. {
  110. unsigned int Read_Number = Requst_Message[4] << 8 | Requst_Message[5];//要读取的寄存器数量
  111. unsigned int Read_Len = Count_Read_date_number(Requst_Message[1
  112. ], Read_Number); //要读取的字节数
  113. for (unsigned int i = 3; i < Read_Len + 3; i= i + 2)
  114. {
  115. Response_Message[i] = Register[Start_Address] >> 8;
  116. Response_Message[i + 1] = (UINT8)Register[Start_Address];
  117. Start_Address += 1;
  118. }
  119. Response_Message[0] = Device_ID;
  120. Response_Message[1] = Requst_Message[1];
  121. Response_Message[2] = Read_Len; //响应报文中的后续字节数
  122. UINT16 CRC_date = CRC_16(Response_Message, Read_Len + 3);
  123. Response_Message_Len = Read_Len + 2 + 3;
  124. Response_Message[Response_Message_Len - 2] = CRC_date >> 8;//CRC_H
  125. Response_Message[Response_Message_Len - 1] = (UINT8)CRC_date; //CRC_L
  126. }
  127. else //地址超限
  128. {
  129. Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x02);
  130. }
  131. }
  132. /*********************************************************************************************
  133. * 功能     :  写入线圈
  134. * 描述    : 将数据写入线圈中
  135. * 输入 : Write_date_Message 要写入的数据 Write_Number要写入的位数 Start_Address起始地址
  136. * 返回值 : 无
  137. **********************************************************************************************/
  138. void Write_Coil_date(UINT8 Write_date_Message, unsigned int Write_Number, unsigned int Start_Address)
  139. {
  140. if (Write_Number >= 8)
  141. {
  142. for (unsigned int i = Start_Address; i < Start_Address+8; i++)
  143. {
  144. Coil_date[i] = Write_date_Message & 1;
  145. Write_date_Message = Write_date_Message >> 1;
  146. }
  147. }
  148. else
  149. {
  150. for (unsigned int i = Start_Address; i < Start_Address + Write_Number; i++)
  151. {
  152. Coil_date[i] = Write_date_Message & 1;
  153. Write_date_Message = Write_date_Message >> 1;
  154. }
  155. }
  156. }
  157. /*********************************************************************************************
  158. * 功能     :  生成0x0F功能码响应报文
  159. * 描述    : 通过判断地址范围生成0x0F对应的响应报文
  160. * 输入 : *Requst_Message 请求报文 *Response_Message响应报文
  161. * 返回值 : 无
  162. **********************************************************************************************/
  163. void Create_0x0F_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message)
  164. {
  165. unsigned int Start_Address = Requst_Message[2] << 8 | Requst_Message[3];
  166. unsigned int Address_range = Start_Address + (Requst_Message[4] << 8 | Requst_Message[5]);
  167. if (Address_range < MAX_Address)//判断地址是否超限
  168. {
  169. unsigned int Write_Number = Requst_Message[4] << 8 | Requst_Message[5];//要写入的位数
  170. for (int i = 7; i < Requst_Message[6]+7; i++)//执行写入线圈操作
  171. {
  172. Write_Coil_date(Requst_Message[i], Write_Number, Start_Address);
  173. Write_Number -= 8;
  174. Start_Address += 8;
  175. }
  176. Response_Message[0] = Device_ID;
  177. Response_Message[1] = Requst_Message[1];
  178. Response_Message[2] = Requst_Message[2];
  179. Response_Message[3] = Requst_Message[3];
  180. Response_Message[4] = Requst_Message[4];
  181. Response_Message[5] = Requst_Message[5];
  182. UINT16 CRC_date = CRC_16(Response_Message, 6);
  183. Response_Message[6] = CRC_date >> 8;//CRC_H
  184. Response_Message[7] = (UINT8)CRC_date; //CRC_L
  185. Response_Message_Len = 8;
  186. }
  187. else //地址超限
  188. {
  189. Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x02);
  190. }
  191. }
  192. /*********************************************************************************************
  193. * 功能     :  生成0x10功能码响应报文
  194. * 描述    : 通过判断地址范围生成0x10对应的响应报文
  195. * 输入 : *Requst_Message 请求报文 *Response_Message响应报文
  196. * 返回值 : 无
  197. **********************************************************************************************/
  198. void Create_0x10_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message)
  199. {
  200. unsigned int Start_Address = Requst_Message[2] << 8 | Requst_Message[3];
  201. unsigned int Address_range = Start_Address + (Requst_Message[4] << 8 | Requst_Message[5]);
  202. if (Address_range < MAX_Address)//判断地址是否超限
  203. {
  204. unsigned int Write_Number = Requst_Message[4] << 8 | Requst_Message[5];//要写入的寄存器个数
  205. for (int i = 7; i < Requst_Message[6] + 7; i = i + 2)//执行写入寄存器操作
  206. {
  207. Register[Start_Address] = Requst_Message[i] << 8 | Requst_Message[i+1];
  208. Start_Address++;
  209. }
  210. Response_Message[0] = Device_ID;
  211. Response_Message[1] = Requst_Message[1];
  212. Response_Message[2] = Requst_Message[2];
  213. Response_Message[3] = Requst_Message[3];
  214. Response_Message[4] = Requst_Message[4];
  215. Response_Message[5] = Requst_Message[5];
  216. UINT16 CRC_date = CRC_16(Response_Message, 6);
  217. Response_Message[6] = CRC_date >> 8;//CRC_H
  218. Response_Message[7] = (UINT8)CRC_date; //CRC_L
  219. Response_Message_Len = 8;
  220. }
  221. else //地址超限
  222. {
  223. Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x02);
  224. }
  225. }
  226. /*********************************************************************************************
  227. * 功能     :  CRC校验
  228. * 描述    : 对请求报文中的数据进行CRC校验
  229. * 输入 : *Requst_Message 请求报文 Read_len 接收到到的字节数
  230. * 返回值 : true CRC校验通过
  231. * false CRC校验不通过
  232. **********************************************************************************************/
  233. bool Check_Requst_Message_CRC(UINT8 *Requst_Message, DWORD Read_len)
  234. {
  235. UINT16 CRC_data = CRC_16(Requst_Message, Read_len-2);
  236. UINT16 Message_CRC = Requst_Message[Read_len - 2] << 8 | Requst_Message[Read_len - 1];
  237. if (CRC_data != Message_CRC)
  238. return false;
  239. return true;
  240. }
  241. /*********************************************************************************************
  242. * 功能     :  异常码03判定--请求报文长度校验
  243. * 描述    : 对请求报文的字节长度进行计算校验
  244. * 输入 : *Requst_Message 请求报文 Read_len 接收到到的字节数
  245. * 返回值 : true 长度校验通过
  246. * false 长度校验不通过
  247. **********************************************************************************************/
  248. bool Check_Requst_Message_Len(UINT8 *Requst_Message, DWORD Read_len)
  249. {
  250. if (Requst_Message[1] == 0x01 || Requst_Message[1] == 0x03)
  251. {
  252. if (Read_len != 8)
  253. return false;
  254. }
  255. if (Requst_Message[1] == 0x0F || Requst_Message[1] == 0x10)
  256. {
  257. unsigned int Number = Requst_Message[4] << 8 | Requst_Message[5];
  258. unsigned int Count_len = Count_Read_date_number(Requst_Message[1], Number) + 9;
  259. if (Read_len != Count_len)
  260. return false;
  261. }
  262. return true;
  263. }
  264. /*********************************************************************************************
  265. * 功能     :  异常码03判定--请求报文中的操作数量判定
  266. * 描述    : 对请求报文中的操作数量进行判定
  267. * 输入 : *Requst_Message 请求报文 Read_len 接收到到的字节数
  268. * 返回值 : true 校验通过
  269. * false 校验不通过
  270. **********************************************************************************************/
  271. bool Check_Operation_Number_Requst_Message(UINT8 *Requst_Message)
  272. {
  273. unsigned int Operation_Number = Requst_Message[4] << 8 | Requst_Message[5];
  274. if (Requst_Message[1] == 0x01)
  275. {
  276. if (Operation_Number == 0 || Operation_Number > 2000)
  277. return false;
  278. }
  279. if (Requst_Message[1] == 0x03)
  280. {
  281. if (Operation_Number == 0 || Operation_Number > 125)
  282. return false;
  283. }
  284. if (Requst_Message[1] == 0x0F)
  285. {
  286. if (Operation_Number < 2 || Operation_Number > 1968)
  287. return false;
  288. }
  289. if (Requst_Message[1] == 0x10)
  290. {
  291. if (Operation_Number < 2 || Operation_Number > 123)
  292. return false;
  293. }
  294. return true;
  295. }
  296. /*********************************************************************************************
  297. * 功能     :  生成响应报文
  298. * 描述    : 检查设备请求报文来生成对应功能的响应报文
  299. * 输入 : *Requst_Message 请求报文 *Response_Message响应报文
  300. * 返回值 : true 生成响应报文
  301. * false 不生成响应报文
  302. **********************************************************************************************/
  303. bool Create_Response_Message(UINT8 *Requst_Message, UINT8 *Response_Message, DWORD Read_len)
  304. {
  305. if (Requst_Message[0] != Device_ID) //检查设备ID一致
  306. return false;
  307. if (!Check_Requst_Message_CRC(Requst_Message, Read_len))//CRC校验报文是否正确
  308. return false;
  309. if (!Check_Requst_Message_Len(Requst_Message, Read_len) || !Check_Operation_Number_Requst_Message(Requst_Message))//检查请求报文长度是否正确
  310. {
  311. Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message, 0x03);
  312. return true;
  313. }
  314. switch (Requst_Message[1])
  315. {
  316. case 0x01:Create_0x01_Response_Message(Requst_Message, Response_Message); break;
  317. case 0x03:Create_0x03_Response_Message(Requst_Message, Response_Message); break;
  318. case 0x0F:Create_0x0F_Response_Message(Requst_Message, Response_Message); break;
  319. case 0x10:Create_0x10_Response_Message(Requst_Message, Response_Message); break;
  320. default: Create_Abnormal_Code_Response_Message(Requst_Message, Response_Message,0x01);
  321. }
  322. return true;
  323. }
  324. int Modbus_RTU_Salve(void)
  325. {
  326. string COMM = Input_COMM();
  327. unsigned int Baud_Rate = Input_Baud_Rate();
  328. BYTE Date_Bits = Input_Date_Bits();
  329. BYTE Stop_Bits = Input_Stop_Bits(Date_Bits);
  330. BYTE Parity = Input_Parity();
  331. UINT8 Requst_Message[MAX_NUMBER];
  332. UINT8 Response_Message[MAX_NUMBER];
  333. HANDLE Handle_Com = Init_COM((LPCTSTR)COMM.c_str(), Baud_Rate, Date_Bits, Stop_Bits, Parity);
  334. if (Handle_Com == INVALID_HANDLE_VALUE)
  335. {
  336. cout << "初始化串口失败" << endl;
  337. getchar();
  338. return 0;
  339. }
  340. else
  341. printf("初始化串口成功");
  342. Init_Coil_Register();
  343. DWORD Read_len;
  344. while (true)
  345. {
  346. PurgeComm(Handle_Com, PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT);//清除缓存
  347. BOOL Read_flage = ReadFile(Handle_Com, Requst_Message, 256, &Read_len, NULL); //阻塞等待接收请求报文
  348. if (Read_flage && (Read_len > 0))
  349. {
  350. if (Create_Response_Message(Requst_Message, Response_Message, Read_len))
  351. {
  352. while (!SendData(Handle_Com, (char*)Response_Message, Response_Message_Len))
  353. {
  354. printf("发送失败,重新发送");
  355. }
  356. Log_Note(Requst_Message, 0, Read_len);
  357. Log_Note(Response_Message, 1, Response_Message_Len);
  358. }
  359. else
  360. continue;
  361. }
  362. }
  363. CloseHandle(Handle_Com);
  364. getchar();
  365. return 0;
  366. }