训练营PLSR题目
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.
 
 
 
 
 
 

693 lines
19 KiB

  1. #include "modbus.h"
  2. uint8_t Coil[1250]; ///<存放线圈的数组
  3. uint8_t Register_H[10000]; ///<寄存器的高字节
  4. uint8_t Register_L[10000]; ///<寄存器的低字节
  5. uint8_t EXRegister_H[10000]; ///<0x10000开始寄存器的高字节
  6. uint8_t EXRegister_L[10000]; ///<0x10000开始寄存器的低字节
  7. uint8_t History[3][512]; /*存放历史的地方*/
  8. uint8_t HistoryLongth[3]; /*历史数据大小的计数*/
  9. uint8_t HistoryLocation; /*当前历史存放到了第几条*/
  10. uint8_t SaveFlag = 0;
  11. uint8_t SentPocket[512];
  12. uint8_t Writr_dat[1024];
  13. /**
  14. * @brief 写单个线圈
  15. * @param[in] addr 写入线圈的地址(第几个线圈)
  16. * @param[in] dat 给线圈写入的值
  17. * @return 无
  18. */
  19. void WriteBit(uint16_t addr,uint8_t dat)
  20. {
  21. uint16_t temp;
  22. temp=addr%8;
  23. if(dat)
  24. {
  25. Coil[addr/8]|= (0x01 << temp);
  26. }
  27. else
  28. {
  29. Coil[addr/8]&=~(0x01 << temp);
  30. }
  31. }
  32. /**
  33. * @brief 读单个线圈
  34. * @param[in] addr 读取线圈的地址(第几个线圈)
  35. * @param[in] *dat 线圈的值放在哪里
  36. * @return 无
  37. */
  38. void ReadBit(uint16_t addr,uint8_t * dat)
  39. {
  40. uint16_t temp;
  41. temp=addr%8;
  42. if((Coil[addr/8])&(0x01 << temp))
  43. {
  44. *dat=0x01;
  45. }
  46. else
  47. {
  48. *dat=0x00;
  49. }
  50. }
  51. /**
  52. * @brief Modbus数据的初始处理
  53. * @param[in] buffer[] 预处理的数据
  54. * @param[in] longth 数据的长度
  55. * @return 无
  56. */
  57. void ProcessModbusFrame(uint8_t buffer[], uint16_t longth)
  58. {
  59. uint8_t crc_8[2], cmdCode;
  60. uint16_t modbusCrc;
  61. modbusCrc = modbus_crc16(buffer, longth - 2);
  62. memcpy(crc_8, &modbusCrc, 2);
  63. cmdCode = buffer[1];
  64. /* 如果通过了CRC校验 */
  65. if (crc_8[0] == buffer[longth - 2] &&
  66. crc_8[1] == buffer[longth - 1])
  67. {
  68. switch (cmdCode)
  69. {
  70. case READ_COIL_CODE: ReadCoilProcess(buffer, longth) /* 读线圈 01 */
  71. ;break;
  72. case WRUTE_MUL_COIL_CODE: WriteMulCoilProcess(buffer, longth) /* 写多线圈 0f */
  73. ;break;
  74. case READ_REGUSTER_CODE: ReadRegisterProcess(buffer, longth) /* 读寄存器 03 */
  75. ;break;
  76. case WRITE_COIL_CODE: WriteCoilProcess(buffer, longth) /* 写线圈 05 */
  77. ;break;
  78. case WRITE_MUL_REGISTER_CODE: WriteMulRegisterProcess(buffer, longth) /* 写多寄存器 10 */
  79. ;break;
  80. case GET_HISTORY_CODE: GetHistory(buffer, longth) /* 获取历史 55 */
  81. ;break;
  82. case READ_ODD_REGUSTER_CODE: ReadOddRegisterProcess(buffer, longth) /* 获取奇数的寄存器 33 */
  83. ;break;
  84. case READ_EXREGUSTER_CODE: ReadEXRegisterProcess(buffer, longth) /* 读0x10000处的寄存器 30*/
  85. ;break;
  86. case WRITE_MUL_EXREGISTER_CODE: WriteEXRegisterProcess(buffer, longth) /* 写0x10000处的寄存器 31*/
  87. ;break;
  88. default :ErrorBack(buffer, longth); /* 无效指令码 */
  89. ;break;
  90. }
  91. }
  92. }
  93. /**
  94. * @brief 0x01指令码的执行,读取多线圈
  95. * @param[in] buffer[] 预处理的数据
  96. * @param[in] longth 数据的长度
  97. * @return 无
  98. */
  99. void ReadCoilProcess (uint8_t buffer[], uint16_t longth)
  100. {
  101. uint16_t startPoint, step, modbusCrc; /* 从哪里开始读取,读取了多少线圈 */
  102. uint8_t sentCount, crc_8[2], temp_data, errCode = 0x00, SentData[400]; /* 要发送多少字节的数据。 crc_8是crc的校验值 temp_data用来存放读到的字节 */
  103. startPoint = (buffer[2] << 8 )| buffer[3]; /* 将8位数据组装为16位 */
  104. step = (buffer[4] << 8) | buffer[5]; /* 将8位数据组装为16位 */
  105. sentCount = step / 8; /* 计算要用多少字节发送 */
  106. if (step % 8 != 0 ) sentCount++; /* 补全发送字节 */
  107. memset(SentData, 0, 400);
  108. /* 如果是与本设备通信 */
  109. if (buffer[0] == SLAVES_ADDRES)
  110. {
  111. /* 异常分析 */
  112. if(longth != 8) errCode = 0x04;
  113. if(startPoint > 0x270f || startPoint + step > 0x270f + 1) errCode = 0x02;
  114. if(step == 0 || step > 0x07d0) errCode = 0x03;
  115. if(errCode == 0x00)
  116. {
  117. for (int i = 0; i < step; i++ )/* 循环到获取完整的字节 */
  118. {
  119. ReadBit(startPoint + i, &temp_data);
  120. SentData[i/8] = SentData[i/8] | (temp_data << (i % 8));
  121. }
  122. /* 准备发送应答 */
  123. SentPocket[0] = 0x01;
  124. SentPocket[1] = 0x01;
  125. SentPocket[2] = sentCount;
  126. for (int j = 0; j < sentCount; j++)/* 数据组装 */
  127. {
  128. memcpy( &SentPocket[3 + j], &SentData[j], 1);
  129. }
  130. modbusCrc = modbus_crc16(SentPocket, 3 + sentCount);/* 计算CRC */
  131. memcpy(crc_8, &modbusCrc, 2);
  132. SentPocket[3 + sentCount] = crc_8[0];
  133. SentPocket[4 + sentCount] = crc_8[1];
  134. HAL_UART_Transmit_DMA(&huart1,SentPocket,5 + sentCount);
  135. SaveHistory(buffer, longth);
  136. }
  137. else
  138. {
  139. /* 准备发送应答 */
  140. SentPocket[0] = 0x01;
  141. SentPocket[1] = buffer[1] + 0x80;
  142. SentPocket[2] = errCode;
  143. modbusCrc = modbus_crc16(SentPocket, 3);/* 计算CRC */
  144. memcpy(crc_8, &modbusCrc, 2);
  145. SentPocket[3] = crc_8[0];
  146. SentPocket[4] = crc_8[1];
  147. HAL_UART_Transmit_DMA(&huart1,SentPocket,5);
  148. }
  149. }
  150. }
  151. /**
  152. * @brief 0x0f指令码的执行,写入多线圈
  153. * @param[in] buffer[] 预处理的数据
  154. * @param[in] longth 数据的长度
  155. * @return 无
  156. */
  157. void WriteMulCoilProcess(uint8_t buffer[], uint16_t longth)
  158. {
  159. uint16_t startPoint,step, modbusCrc; /* 从哪里开始写入,写入的终点,写入了多少线圈 */
  160. uint8_t crc_8[2],datCount, errCode = 0x00, sentCount; /* crc_8是crc的校验值,datCount,数据计数,有多少位的数据,Writr_dat存放要写入的数据 */
  161. startPoint = (buffer[2] << 8 )| buffer[3]; /* 将8位数据组装位16位 */
  162. step = (buffer[4] << 8) | buffer[5]; /* 将8位数据组装位16位 */
  163. datCount = buffer[6];
  164. memset(Writr_dat, 0, 1024);
  165. sentCount = step / 8; /* 计算要用多少字节发送 */
  166. if (step % 8 != 0 ) sentCount++; /* 补全发送字节 */
  167. /*数据转移,将buffer内的数据存如写数组。*/
  168. for (int i = 0; i < datCount; i++)
  169. {
  170. Writr_dat[i] = buffer[i + 7];
  171. }
  172. /* 如果是与本设备通信 */
  173. if((buffer[0] == SLAVES_ADDRES || buffer[0] == 0x00))
  174. {
  175. /* 异常分析 */
  176. if(buffer[6] + 9 != longth) errCode = 0x04;
  177. if(startPoint > 0x270f || startPoint + step > 0x270f) errCode = 0x02;
  178. if(step == 0 || step > 0x07b0 || sentCount != datCount) errCode = 0x03;
  179. if(errCode == 0x00)
  180. {
  181. for (int j = 0; j < step; j++)
  182. {
  183. if ((Writr_dat[j / 8]) & (0x01)<<(j % 8))
  184. {
  185. WriteBit(startPoint + j, 0x01);
  186. }
  187. else
  188. {
  189. WriteBit(startPoint + j, 0x00);
  190. }
  191. }
  192. /* 如果不是广播,发送返回消息 */
  193. if(buffer[0] == SLAVES_ADDRES)
  194. {
  195. /* 准备发送应答 */
  196. SentPocket[0] = 0x01;
  197. SentPocket[1] = 0x0f;
  198. SentPocket[2] = buffer[2];
  199. SentPocket[3] = buffer[3];
  200. SentPocket[4] = buffer[4];
  201. SentPocket[5] = buffer[5];
  202. modbusCrc = modbus_crc16(SentPocket, 6);/* 计算CRC */
  203. memcpy(crc_8, &modbusCrc, 2);
  204. SentPocket[6] = crc_8[0];
  205. SentPocket[7] = crc_8[1];
  206. HAL_UART_Transmit_DMA(&huart1,SentPocket,8);
  207. SaveHistory(buffer, longth);
  208. }
  209. }
  210. else if(errCode != 0x00 && buffer[0] == SLAVES_ADDRES)
  211. {
  212. /* 准备发送应答 */
  213. SentPocket[0] = 0x01;
  214. SentPocket[1] = buffer[1] + 0x80;
  215. SentPocket[2] = errCode;
  216. modbusCrc = modbus_crc16(SentPocket, 3);/* 计算CRC */
  217. memcpy(crc_8, &modbusCrc, 2);
  218. SentPocket[3] = crc_8[0];
  219. SentPocket[4] = crc_8[1];
  220. HAL_UART_Transmit_DMA(&huart1,SentPocket,5);
  221. }
  222. }
  223. }
  224. /**
  225. * @brief 0x03指令码的执行,读出输出寄存器
  226. * @param[in] buffer[] 预处理的数据
  227. * @param[in] longth 数据的长度
  228. * @return 无
  229. */
  230. void ReadRegisterProcess(uint8_t buffer[], uint16_t longth)
  231. {
  232. uint16_t startPoint,step, modbusCrc; /* 从哪里开始读取,读取多少寄存器 */
  233. uint8_t crc_8[2], SentData[256], errCode = 0x00;
  234. startPoint = (buffer[2] << 8 )| buffer[3]; /* 将8位数据组装位16位 */
  235. step = (buffer[4] << 8) | buffer[5]; /* 将8位数据组装位16位 */
  236. /* 如果是与本设备通信 */
  237. if (buffer[0] == SLAVES_ADDRES)
  238. {
  239. if(longth != 8) errCode = 0x04;
  240. if(startPoint > 0x270f || startPoint + step > 0x270f + 1) errCode = 0x02;
  241. if(step == 0 || step > 0x007d) errCode = 0x03;
  242. if(errCode == 0x00)
  243. {
  244. for (int i = 0; i < step; i++) /* 将数据存取发出数据缓存 */
  245. {
  246. SentData[i * 2] = Register_H[startPoint + i];
  247. SentData[i * 2 +1 ] = Register_L[startPoint + i];
  248. }
  249. /* 准备发送应答 */
  250. SentPocket[0] = 0x01;
  251. SentPocket[1] = 0x03;
  252. SentPocket[2] = buffer[5] * 2;
  253. for (int j = 0; j < buffer[5] * 2; j++)/* 数据组装 */
  254. {
  255. SentPocket[3+j] = SentData[j];
  256. }
  257. modbusCrc = modbus_crc16(SentPocket, (buffer[5] * 2)+ 3);/* 计算CRC */
  258. memcpy(crc_8, &modbusCrc, 2);
  259. SentPocket[(buffer[5] * 2)+ 3] = crc_8[0];
  260. SentPocket[(buffer[5] * 2)+ 4] = crc_8[1];
  261. HAL_UART_Transmit_DMA(&huart1,SentPocket,(buffer[5] * 2)+ 5 );
  262. SaveHistory(buffer, longth);
  263. }
  264. else
  265. {
  266. /* 准备发送应答 */
  267. SentPocket[0] = 0x01;
  268. SentPocket[1] = buffer[1] + 0x80;
  269. SentPocket[2] = errCode;
  270. modbusCrc = modbus_crc16(SentPocket, 3);/* 计算CRC */
  271. memcpy(crc_8, &modbusCrc, 2);
  272. SentPocket[3] = crc_8[0];
  273. SentPocket[4] = crc_8[1];
  274. HAL_UART_Transmit_DMA(&huart1,SentPocket,5);
  275. }
  276. }
  277. }
  278. /**
  279. * @brief 0x30指令码的执行,读出额外输出寄存器
  280. * @param[in] buffer[] 预处理的数据
  281. * @param[in] longth 数据的长度
  282. * @return 无
  283. */
  284. void ReadEXRegisterProcess(uint8_t buffer[], uint16_t longth)
  285. {
  286. uint16_t startPoint,step, modbusCrc; /* 从哪里开始读取,读取多少寄存器 */
  287. uint8_t crc_8[2], SentData[256], errCode = 0x00;
  288. startPoint = (buffer[2] << 8 )| buffer[3]; /* 将8位数据组装位16位 */
  289. step = (buffer[4] << 8) | buffer[5]; /* 将8位数据组装位16位 */
  290. /* 如果是与本设备通信 */
  291. if (buffer[0] == SLAVES_ADDRES)
  292. {
  293. if(longth != 8) errCode = 0x04;
  294. if(startPoint > 0x270f || startPoint + step > 0x270f + 1) errCode = 0x02;
  295. if(step == 0 || step > 0x007d) errCode = 0x03;
  296. if(errCode == 0x00)
  297. {
  298. for (int i = 0; i < step; i++) /* 将数据存取发出数据缓存 */
  299. {
  300. SentData[i * 2] = EXRegister_H[startPoint + i];
  301. SentData[i * 2 +1 ] = EXRegister_L[startPoint + i];
  302. }
  303. /* 准备发送应答 */
  304. SentPocket[0] = 0x01;
  305. SentPocket[1] = 0x30;
  306. SentPocket[2] = buffer[5] * 2;
  307. for (int j = 0; j < buffer[5] * 2; j++)/* 数据组装 */
  308. {
  309. SentPocket[3+j] = SentData[j];
  310. }
  311. modbusCrc = modbus_crc16(SentPocket, (buffer[5] * 2)+ 3);/* 计算CRC */
  312. memcpy(crc_8, &modbusCrc, 2);
  313. SentPocket[(buffer[5] * 2)+ 3] = crc_8[0];
  314. SentPocket[(buffer[5] * 2)+ 4] = crc_8[1];
  315. HAL_UART_Transmit_DMA(&huart1,SentPocket,(buffer[5] * 2)+ 5 );
  316. SaveHistory(buffer, longth);
  317. }
  318. else
  319. {
  320. /* 准备发送应答 */
  321. SentPocket[0] = 0x01;
  322. SentPocket[1] = buffer[1] + 0x80;
  323. SentPocket[2] = errCode;
  324. modbusCrc = modbus_crc16(SentPocket, 3);/* 计算CRC */
  325. memcpy(crc_8, &modbusCrc, 2);
  326. SentPocket[3] = crc_8[0];
  327. SentPocket[4] = crc_8[1];
  328. HAL_UART_Transmit_DMA(&huart1,SentPocket,5);
  329. }
  330. }
  331. }
  332. /**
  333. * @brief 0x33指令码的执行,读取奇数位寄存器
  334. * @param[in] buffer[] 预处理的数据
  335. * @param[in] longth 数据的长度
  336. * @return 无
  337. */
  338. void ReadOddRegisterProcess(uint8_t buffer[], uint16_t longth)
  339. {
  340. uint16_t startPoint,step, modbusCrc; /* 从哪里开始读取,读取多少寄存器 */
  341. uint8_t crc_8[2], SentData[256], errCode = 0x00;
  342. startPoint = (buffer[2] << 8 )| buffer[3]; /* 将8位数据组装位16位 */
  343. step = (buffer[4] << 8) | buffer[5]; /* 将8位数据组装位16位 */
  344. /* 如果是与本设备通信 */
  345. if (buffer[0] == SLAVES_ADDRES)
  346. {
  347. if(longth != 8) errCode = 0x04;
  348. if(startPoint > 0x270f || startPoint + step > 0x270f + 1 || startPoint % 2 == 0) errCode = 0x02;
  349. if(step == 0 || step > 0x007d) errCode = 0x03;
  350. if(errCode == 0x00)
  351. {
  352. for (int i = 0; i < step * 2; i+= 2) /* 将数据存取发出数据缓存 */
  353. {
  354. SentData[i] = Register_H[startPoint + i];
  355. SentData[i + 1] = Register_L[startPoint + i];
  356. }
  357. /* 准备发送应答 */
  358. SentPocket[0] = 0x01;
  359. SentPocket[1] = 0x33;
  360. SentPocket[2] = step * 2;
  361. for (int j = 0; j < step * 2; j++)/* 数据组装 */
  362. {
  363. SentPocket[3+j] = SentData[j];
  364. }
  365. modbusCrc = modbus_crc16(SentPocket, step * 2 + 3);/* 计算CRC */
  366. memcpy(crc_8, &modbusCrc, 2);
  367. SentPocket[(buffer[5] * 2)+ 3] = crc_8[0];
  368. SentPocket[(buffer[5] * 2)+ 4] = crc_8[1];
  369. HAL_UART_Transmit_DMA(&huart1,SentPocket,(step * 2)+ 5 );
  370. SaveHistory(buffer, longth);
  371. }
  372. else
  373. {
  374. /* 准备发送应答 */
  375. SentPocket[0] = 0x01;
  376. SentPocket[1] = buffer[1] + 0x80;
  377. SentPocket[2] = errCode;
  378. modbusCrc = modbus_crc16(SentPocket, 3);/* 计算CRC */
  379. memcpy(crc_8, &modbusCrc, 2);
  380. SentPocket[3] = crc_8[0];
  381. SentPocket[4] = crc_8[1];
  382. HAL_UART_Transmit_DMA(&huart1,SentPocket,5);
  383. }
  384. }
  385. }
  386. /**
  387. * @brief 0x10指令码的执行,写入多寄存器
  388. * @param[in] buffer[] 预处理的数据
  389. * @param[in] longth 数据的长度
  390. * @return 无
  391. */
  392. void WriteMulRegisterProcess(uint8_t buffer[], uint16_t longth)
  393. {
  394. uint16_t startPoint, step, modbusCrc; /* 从哪里开始写入,写入多少寄存器 */
  395. uint8_t crc_8[2], datCount, errCode = 0x00; /* crc校验;数据计数 */
  396. startPoint = (buffer[2] << 8 )| buffer[3]; /* 将8位数据组装位16位 */
  397. step = (buffer[4] << 8) | buffer[5]; /* 将8位数据组装位16位 */
  398. datCount = buffer[6] / 2;
  399. /* 如果是与本设备通信 */
  400. if ((buffer[0] == SLAVES_ADDRES || buffer[0] == 0x00))
  401. {
  402. if(buffer[6] + 9 != longth) errCode = 0x04;
  403. if(startPoint > 0x270f || startPoint + step > 0x270f + 1) errCode = 0x02;
  404. if(step == 0x00 || step > 0x07b || step * 2 != buffer[6] ) errCode = 0x03;
  405. if(errCode == 0x00)
  406. {
  407. for (int i = 0; i < datCount; i++) /* 数据写入 */
  408. {
  409. Register_H[startPoint + i] = buffer[(i * 2)+ 7];
  410. Register_L[startPoint + i] = buffer[(i * 2)+ 8];
  411. }
  412. /* 如果不是广播,发送返回消息 */
  413. if(buffer[0] == SLAVES_ADDRES)
  414. {
  415. /* 准备发送应答 */
  416. SentPocket[0] = 0x01;
  417. SentPocket[1] = 0x10;
  418. SentPocket[2] = buffer[2];
  419. SentPocket[3] = buffer[3];
  420. SentPocket[4] = buffer[4];
  421. SentPocket[5] = buffer[5];
  422. modbusCrc = modbus_crc16(SentPocket, 6);/* 计算CRC */
  423. memcpy(crc_8, &modbusCrc, 2);
  424. SentPocket[6] = crc_8[0];
  425. SentPocket[7] = crc_8[1];
  426. HAL_UART_Transmit_DMA(&huart1,SentPocket,8);
  427. SaveHistory(buffer, longth);
  428. }
  429. }
  430. else if(errCode != 0x00 && buffer[0] == SLAVES_ADDRES)
  431. {
  432. /* 准备发送应答 */
  433. SentPocket[0] = 0x01;
  434. SentPocket[1] = buffer[1] + 0x80;
  435. SentPocket[2] = errCode;
  436. modbusCrc = modbus_crc16(SentPocket, 3);/* 计算CRC */
  437. memcpy(crc_8, &modbusCrc, 2);
  438. SentPocket[3] = crc_8[0];
  439. SentPocket[4] = crc_8[1];
  440. HAL_UART_Transmit_DMA(&huart1,SentPocket,5);
  441. }
  442. }
  443. }
  444. /**
  445. * @brief 0x31指令码的执行,写入额外多寄存器
  446. * @param[in] buffer[] 预处理的数据
  447. * @param[in] longth 数据的长度
  448. * @return 无
  449. */
  450. void WriteEXRegisterProcess(uint8_t buffer[], uint16_t longth)
  451. {
  452. uint16_t startPoint, step, modbusCrc; /* 从哪里开始写入,写入多少寄存器 */
  453. uint8_t crc_8[2], datCount, errCode = 0x00; /* crc校验;数据计数 */
  454. startPoint = (buffer[2] << 8 )| buffer[3]; /* 将8位数据组装位16位 */
  455. step = (buffer[4] << 8) | buffer[5]; /* 将8位数据组装位16位 */
  456. datCount = buffer[6] / 2;
  457. /* 如果是与本设备通信 */
  458. if ((buffer[0] == SLAVES_ADDRES || buffer[0] == 0x00))
  459. {
  460. if(buffer[6] + 9 != longth) errCode = 0x04;
  461. if(startPoint > 0x270f || startPoint + step > 0x270f + 1) errCode = 0x02;
  462. if(step == 0x00 || step > 0x07b || step * 2 != buffer[6] ) errCode = 0x03;
  463. if(errCode == 0x00)
  464. {
  465. for (int i = 0; i < datCount; i++) /* 数据写入 */
  466. {
  467. EXRegister_H[startPoint + i] = buffer[(i * 2)+ 7];
  468. EXRegister_L[startPoint + i] = buffer[(i * 2)+ 8];
  469. }
  470. /* 如果不是广播,发送返回消息 */
  471. if(buffer[0] == SLAVES_ADDRES)
  472. {
  473. /* 准备发送应答 */
  474. SentPocket[0] = 0x01;
  475. SentPocket[1] = 0x31;
  476. SentPocket[2] = buffer[2];
  477. SentPocket[3] = buffer[3];
  478. SentPocket[4] = buffer[4];
  479. SentPocket[5] = buffer[5];
  480. modbusCrc = modbus_crc16(SentPocket, 6);/* 计算CRC */
  481. memcpy(crc_8, &modbusCrc, 2);
  482. SentPocket[6] = crc_8[0];
  483. SentPocket[7] = crc_8[1];
  484. HAL_UART_Transmit_DMA(&huart1,SentPocket,8);
  485. SaveHistory(buffer, longth);
  486. }
  487. }
  488. else if(errCode != 0x00 && buffer[0] == SLAVES_ADDRES)
  489. {
  490. /* 准备发送应答 */
  491. SentPocket[0] = 0x01;
  492. SentPocket[1] = buffer[1] + 0x80;
  493. SentPocket[2] = errCode;
  494. modbusCrc = modbus_crc16(SentPocket, 3);/* 计算CRC */
  495. memcpy(crc_8, &modbusCrc, 2);
  496. SentPocket[3] = crc_8[0];
  497. SentPocket[4] = crc_8[1];
  498. HAL_UART_Transmit_DMA(&huart1,SentPocket,5);
  499. }
  500. }
  501. }
  502. /**
  503. * @brief 0x05指令码的执行,写入单线圈
  504. * @param[in] buffer[] 预处理的数据
  505. * @param[in] longth 数据的长度
  506. * @return 无
  507. */
  508. void WriteCoilProcess(uint8_t buffer[], uint16_t longth)
  509. {
  510. uint16_t startPoint, State; /* 从哪里开始写入,写入多少寄存器 */
  511. startPoint = (buffer[2] << 8 )| buffer[3]; /* 将8位数据组装位16位 */
  512. State = (buffer[4] << 8) | buffer[5]; /* 将8位数据组装位16位 */
  513. if ((buffer[0] == SLAVES_ADDRES || buffer[0] == 0x00))/* 如果是与本设备通信 */
  514. {
  515. if(State == 0xff00)
  516. {
  517. Coil[startPoint/8]|= (0x01 << (startPoint % 8) );
  518. }
  519. if(State == 0x0000)
  520. {
  521. Coil[startPoint/8]&=~(0x01 << (startPoint % 8) );
  522. }
  523. /* 如果不是广播,发送返回消息 */
  524. if(buffer[0] == SLAVES_ADDRES)
  525. {
  526. HAL_UART_Transmit_DMA(&huart1, buffer, longth);
  527. }
  528. }
  529. }
  530. /**
  531. * @brief 指令码错误的返回报文
  532. * @param[in] buffer[] 预处理的数据
  533. * @param[in] longth 数据的长度
  534. * @return 无
  535. */
  536. void ErrorBack(uint8_t buffer[], uint16_t longth)
  537. {
  538. uint16_t modbusCrc;
  539. uint8_t crc_8[2];
  540. /* 如果是与本设备通信 */
  541. if (buffer[0] == SLAVES_ADDRES)
  542. {
  543. /* 准备发送应答 */
  544. SentPocket[0] = 0x01;
  545. SentPocket[1] = buffer[1] + 0x80;
  546. SentPocket[2] = 0x01;
  547. modbusCrc = modbus_crc16(SentPocket, 3);/* 计算CRC */
  548. memcpy(crc_8, &modbusCrc, 2);
  549. SentPocket[3] = crc_8[0];
  550. SentPocket[4] = crc_8[1];
  551. HAL_UART_Transmit_DMA(&huart1,SentPocket,5);
  552. }
  553. }
  554. /**
  555. * @brief 历史保存
  556. * @param[in] buffer[] 保存的数据
  557. * @param[in] longth 数据的长度
  558. * @return 无
  559. */
  560. void SaveHistory(uint8_t buffer[], uint16_t longth)
  561. {
  562. memcpy(History[HistoryLocation], buffer, longth);
  563. HistoryLongth[HistoryLocation] = longth;
  564. HistoryLocation++;
  565. if(HistoryLocation == 3)
  566. {
  567. HistoryLocation = 0;
  568. }
  569. }
  570. /**
  571. * @brief 历史读取
  572. * @return 无
  573. */
  574. void LoadHistory(void)
  575. {
  576. uint8_t temp;
  577. temp = HistoryLocation;
  578. for(int i = 0; i < 3; i++)
  579. {
  580. if(temp == 3)
  581. {
  582. temp = 0;
  583. }
  584. HAL_UART_Transmit(&huart1, History[temp], HistoryLongth[temp], 0xffff);
  585. temp++;
  586. }
  587. }
  588. /**
  589. * @brief 0x55指令码的执行,输出历史
  590. * @param[in] buffer[] 预处理的数据
  591. * @param[in] longth 数据的长度
  592. * @return 无
  593. */
  594. void GetHistory(uint8_t buffer[], uint16_t longth)
  595. {
  596. /* 如果是与本设备通信 */
  597. if (buffer[0] == SLAVES_ADDRES)
  598. {
  599. LoadHistory();
  600. }
  601. }
  602. /**
  603. * @brief 读取并还原sram数据。
  604. * @return 无
  605. */
  606. void ModbusLoadSRAM(void)
  607. {
  608. uint32_t temp[5];
  609. Read_Backup_SRAM(temp,5);
  610. memcpy(SramData, temp, 20);
  611. for(int i = 0; i < 10; i++)
  612. {
  613. Register_H[i] = SramData[i * 2];
  614. Register_L[i] = SramData[i * 2 + 1];
  615. }
  616. }
  617. /**
  618. * @brief 存入sram数据。
  619. * @return 无
  620. */
  621. void ModbusSaveSRAM(void)
  622. {
  623. uint32_t temp[5];
  624. for (int i = 0; i < 10; i++)
  625. {
  626. SramData[i * 2] = Register_H[i];
  627. SramData[i * 2 + 1] = Register_L[i];
  628. }
  629. memcpy(temp, SramData, 20);
  630. Write_Backup_SRAM(temp, 5);
  631. }