Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 

705 řádky
19 KiB

  1. #include "stm32f4xx.h"
  2. #include "ucos_ii.h"
  3. #include "os.h"
  4. #include "string.h"
  5. #include "modbus.h"
  6. extern OS_EVENT* ModbusWriteFlash; /*接收到modbus写入coil请求报文*/
  7. extern OS_EVENT* ModbusConnect; /*已接收到modbus正确报文*/
  8. uint8_t ModbusErr;
  9. /*0x270F + 1 = K10000 */
  10. uint8_t ModbusCoil[1250]; /*10000/8=1250*/
  11. uint16_t ModbusReg[10000];
  12. /*附加功能:页寄存器*/
  13. uint16_t ModbusExtPage[1] = {0}; /*设置地址为0xFFFE*/
  14. uint16_t ModbusExtReg[1]; /*地址映射为0x10000*/
  15. /*附加功能:读取所有单数个寄存器*/
  16. uint16_t ModbusExtOdd[1] = {0}; /*设置地址为0xFFFF*/
  17. uint8_t ModbusRxBuf[MODBUS_RX_BUF_SIZE]; /*接收数组*/
  18. uint16_t ModbusRxLen = 0; /*接收数据长度*/
  19. uint8_t ModbusTxBuf[MODBUS_TX_BUF_SIZE]; /*发送数组*/
  20. uint16_t ModbusTxLen = 0; /*发送数据长度*/
  21. uint8_t ModbusErrReply(uint8_t func, uint8_t err);
  22. uint16_t Crc16(const uint8_t *data, uint16_t length);
  23. void AddCrc16(uint8_t *data, uint16_t length);
  24. int8_t ChcekCrc16(uint16_t recCrc16, uint8_t *data, uint16_t length);
  25. uint8_t ModbusReadCoils(uint16_t addres, uint16_t num);
  26. uint8_t ModbusWriteCoils(uint16_t addres, uint16_t num, uint8_t *data);
  27. uint8_t ModbusReadRegs(uint16_t addres, uint16_t num);
  28. uint8_t ModbusWriteRegs(uint16_t addres, uint16_t num, uint8_t *data);
  29. uint8_t ModbusWriteReg(uint16_t addres, uint8_t *data);
  30. uint8_t ModbusWriteCoil(uint16_t addres, uint8_t *data);
  31. uint8_t ModbusExtReadOdd(uint16_t num);
  32. /*USART接收空闲中断*/
  33. void USART1_IRQHandler(void)
  34. {
  35. OSIntEnter(); /*进入中断*/
  36. uint32_t temp;
  37. uint16_t rxLenRemain;
  38. if(USART_GetITStatus(USART1, USART_IT_IDLE) == SET)
  39. {
  40. /*在计算数据长度之前先关闭DMA接收通道,防止计算过程中DMA继续转运数据*/
  41. DMA_Cmd(DMA2_Stream2, DISABLE);
  42. /*清除IDLE中断标志位*/
  43. temp = USART1->SR;
  44. temp = USART1->DR;
  45. (void)temp;
  46. /*清除传输已经完成TCIF2、传输已经完成一半HTIF2标志位*/
  47. DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_TCIF2 | DMA_FLAG_HTIF2);
  48. /*计算数据长度*/
  49. rxLenRemain = DMA_GetCurrDataCounter(DMA2_Stream2);
  50. ModbusRxLen = MODBUS_RX_BUF_SIZE - rxLenRemain;
  51. /*释放接收到数据帧信号量,唤醒帧解析任务*/
  52. if(ModbusRxLen != 0)
  53. {
  54. OSSemPost(ModbusReceived);
  55. }
  56. /*重新指定接收地址*/
  57. DMA_MemoryTargetConfig(DMA2_Stream2, (uint32_t)ModbusRxBuf, DMA_Memory_0);
  58. /*重启DMA*/
  59. DMA_SetCurrDataCounter(DMA2_Stream2, MODBUS_RX_BUF_SIZE);
  60. DMA_Cmd(DMA2_Stream2, ENABLE);
  61. }
  62. OSIntExit(); /*退出中断*/
  63. }
  64. /*modbus响应帧发送*/
  65. void ModbusSend(uint8_t *txBuf, uint16_t len)
  66. {
  67. if(DMA_GetCmdStatus(DMA2_Stream7) == ENABLE)
  68. {
  69. /*等待DMA发送完成*/
  70. while(DMA_GetFlagStatus(DMA2_Stream7, DMA_FLAG_TCIF7) == RESET);
  71. }
  72. /*先关闭DMA发送通道*/
  73. DMA_Cmd(DMA2_Stream7, DISABLE);
  74. /*等待DMA关闭*/
  75. while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE);
  76. /*清除传输已经完成TCIF7、传输已经完成一半HTIF7、FIFO错误FEIF7标志位*/
  77. DMA_ClearFlag(DMA2_Stream7, DMA_FLAG_FEIF7 | DMA_FLAG_HTIF7 | DMA_FLAG_TCIF7);
  78. /*配置发送地址和长度*/
  79. DMA_MemoryTargetConfig(DMA2_Stream7, (uint32_t)txBuf, DMA_Memory_0);
  80. DMA_SetCurrDataCounter(DMA2_Stream7, len);
  81. /*等待串口发送完成*/
  82. while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
  83. /*在此处等待3.5个字符的时间*/
  84. /*启动 DMA 发送*/
  85. DMA_Cmd(DMA2_Stream7, ENABLE);
  86. }
  87. /*modbus协议帧解析任务*/
  88. void AppTaskModbusParse (void *p_arg)
  89. {
  90. OS_ERR err;
  91. MODBUS_FRAME frame;
  92. uint16_t rxLen;
  93. uint8_t rxBuf[256];
  94. while(1)
  95. {
  96. /*无限期等待接收到数据帧信号量*/
  97. OSSemPend(ModbusReceived, 0, &err);
  98. /*数据接收,防止下一帧覆盖*/
  99. rxLen = ModbusRxLen;
  100. memcpy(rxBuf, ModbusRxBuf, rxLen);
  101. /*拼接crc校验码(高前低后),接收到的数据帧crc校验码是低前高后*/
  102. frame.crc = ((uint16_t)(rxBuf[rxLen - 2])) | ((uint16_t)rxBuf[rxLen - 1] << 8);
  103. if(ChcekCrc16(frame.crc, rxBuf, rxLen) != 0)
  104. {
  105. /*crc校验错误,直接丢弃*/
  106. ModbusErr = ERR_CRC;
  107. continue;
  108. }
  109. frame.slaveAddres = rxBuf[0];
  110. if(frame.slaveAddres != SLAVE_ADDRES)
  111. {
  112. /*从机地址错误,直接丢弃*/
  113. ModbusErr = ERR_SLAVE_ADDRES;
  114. continue;
  115. }
  116. OSSemPost(ModbusConnect);
  117. frame.func = rxBuf[1];
  118. frame.opeAddres = ((uint16_t)rxBuf[2] << 8) | ((uint16_t)rxBuf[3]);
  119. frame.opeNum = ((uint16_t)rxBuf[4] << 8) | ((uint16_t)rxBuf[5]);
  120. /*功能码分类*/
  121. switch(frame.func)
  122. {
  123. case 0x01:/*读线圈*/
  124. ModbusErr = ModbusReadCoils(frame.opeAddres, frame.opeNum);
  125. break;
  126. case 0x03:/*读寄存器*/
  127. ModbusErr = ModbusReadRegs(frame.opeAddres, frame.opeNum);
  128. break;
  129. case 0x0F:/*写多个线圈*/
  130. frame.wNum = rxBuf[6];
  131. memcpy(frame.wData, &rxBuf[7], frame.wNum);
  132. ModbusErr = ModbusWriteCoils(frame.opeAddres, frame.opeNum, frame.wData);
  133. if(ModbusErr == 0)
  134. {
  135. OSSemPost(ModbusWriteFlash);
  136. }
  137. break;
  138. case 0x10:/*写多个寄存器*/
  139. frame.wNum = rxBuf[6];
  140. memcpy(frame.wData, &rxBuf[7], frame.wNum);
  141. ModbusErr = ModbusWriteRegs(frame.opeAddres, frame.opeNum, frame.wData);
  142. if(ModbusErr == 0)
  143. {
  144. OSSemPost(ModbusWriteFlash);
  145. }
  146. break;
  147. case 0x05:/*写单个线圈*/
  148. memcpy(frame.wData, &rxBuf[4], 2);
  149. ModbusErr = ModbusWriteCoil(frame.opeAddres, frame.wData);
  150. if(ModbusErr == 0)
  151. {
  152. OSSemPost(ModbusWriteFlash);
  153. }
  154. break;
  155. case 0x06:/*写单个寄存器*/
  156. memcpy(frame.wData, &rxBuf[4], 2);
  157. ModbusErr = ModbusWriteReg(frame.opeAddres, frame.wData);
  158. if(ModbusErr == 0)
  159. {
  160. OSSemPost(ModbusWriteFlash);
  161. }
  162. break;
  163. default:/*功能码错误*/
  164. ModbusErr = ERR_FUNC;
  165. ModbusErr = ModbusErrReply(frame.func, ERR_FUNC);
  166. break;
  167. }
  168. /*实现附加功能时不在这里启动发送*/
  169. if(frame.func == 0x03 && frame.opeAddres == 0XFFFF)
  170. {
  171. ;
  172. }
  173. else
  174. {
  175. /*启动发送*/
  176. ModbusSend(ModbusTxBuf, ModbusTxLen);
  177. }
  178. }
  179. }
  180. uint8_t ModbusReadCoils(uint16_t addres, uint16_t num)
  181. {
  182. uint16_t byteIndI; /*字节索引*/
  183. uint8_t bitIndI; /*位索引*/
  184. uint16_t byteIndO;
  185. uint8_t bitIndO;
  186. uint8_t dataLen; /*响应帧返回字节数*/
  187. uint8_t index; /*发送数组索引*/
  188. uint8_t readVal; /*读取到的形式值*/
  189. uint8_t writeVal; /*写入的形式值*/
  190. if(ModbusRxLen < 8)
  191. {
  192. return ModbusErrReply(0x01, ERR_DATA);
  193. }
  194. /*操作地址超限*/
  195. if(addres > 0x270F || (addres + (num - 1)) > 0x270F)
  196. {
  197. return ModbusErrReply(0x01, ERR_OPE_ADDRES);
  198. }
  199. /*操作数量超限*/
  200. if(num == 0 || num > 2000)
  201. {
  202. return ModbusErrReply(0x01, ERR_DATA);
  203. }
  204. /*不能num/8+1,当为8的整数时会多一个*/
  205. dataLen = (num + 7) / 8;
  206. /*清零发送数组*/
  207. memset(&ModbusTxBuf[3], 0, 253);
  208. for(uint16_t i = 0; i < num; i++)
  209. {
  210. byteIndO = i / 8;
  211. bitIndO = i % 8;
  212. byteIndI = (addres + i) / 8;
  213. bitIndI = (addres + i) % 8;
  214. /*位掩码读取线圈值*/
  215. readVal = ModbusCoil[byteIndI] & ((uint8_t)1 << bitIndI);
  216. /*读取到的值为0则不进行操作*/
  217. if(readVal != 0)
  218. {
  219. index = 3 + byteIndO;
  220. /*将读取到的值移位到要写入的位*/
  221. writeVal = (uint8_t)1u << bitIndO;
  222. ModbusTxBuf[index] |= writeVal;
  223. }
  224. }
  225. ModbusTxBuf[0] = SLAVE_ADDRES; /*从机地址*/
  226. ModbusTxBuf[1] = 0x01; /*功能码*/
  227. ModbusTxBuf[2] = dataLen; /*响应帧返回数据字节数*/
  228. AddCrc16(ModbusTxBuf, 3 + dataLen);
  229. ModbusTxLen = 5 + dataLen;
  230. return 0;
  231. }
  232. uint8_t ModbusWriteCoils(uint16_t addres, uint16_t num, uint8_t *data)
  233. {
  234. uint16_t byteIndI;
  235. uint8_t bitIndI;
  236. uint16_t byteIndO;
  237. uint8_t bitIndO;
  238. uint8_t readVal;
  239. uint8_t writeVal;
  240. if(ModbusRxLen < 10)
  241. {
  242. return ModbusErrReply(0x0F, ERR_DATA);
  243. }
  244. /*操作地址超限*/
  245. if(addres > 0x270F || (addres + (num - 1)) > 0x270F)
  246. {
  247. return ModbusErrReply(0x0F, ERR_OPE_ADDRES);
  248. }
  249. /*操作数量超限*/
  250. if(num == 0 || num > 1968)
  251. {
  252. return ModbusErrReply(0x0F, ERR_DATA);
  253. }
  254. for(uint16_t i = 0; i < num; i++)
  255. {
  256. byteIndI = (addres + i) / 8;
  257. bitIndI = (addres + i) % 8;
  258. byteIndO = i / 8;
  259. bitIndO = i % 8;
  260. /*位掩码读取要写入的值*/
  261. readVal = data[byteIndO] | ((uint8_t)1 << bitIndO);
  262. /*将写入值移位到要写入的位*/
  263. writeVal = (uint8_t)1 << bitIndI;
  264. /*对应位写入1*/
  265. if(readVal != 0)
  266. {
  267. ModbusCoil[byteIndI] |= writeVal;
  268. }
  269. /*对应位写入0*/
  270. else
  271. {
  272. ModbusCoil[byteIndI] &= (~writeVal);
  273. }
  274. }
  275. ModbusTxBuf[0] = SLAVE_ADDRES;
  276. ModbusTxBuf[1] = 0x0F;
  277. /*操作地址*/
  278. ModbusTxBuf[2] = (uint8_t)(addres >> 8);
  279. ModbusTxBuf[3] = (uint8_t)(addres & 0x00FF);
  280. /*成功写入的数量*/
  281. ModbusTxBuf[4] = (uint8_t)(num >> 8);
  282. ModbusTxBuf[5] = (uint8_t)(num & 0x00FF);
  283. AddCrc16(ModbusTxBuf, 6);
  284. ModbusTxLen = 8;
  285. return 0;
  286. }
  287. uint8_t ModbusReadRegs(uint16_t addres, uint16_t num)
  288. {
  289. uint8_t index;
  290. uint8_t readValH;
  291. uint8_t readValL;
  292. uint8_t dataLen;
  293. if(ModbusRxLen < 8)
  294. {
  295. return ModbusErrReply(0x13, ERR_DATA);
  296. }
  297. /*操作地址超限*/
  298. if(addres > 0x270F || (addres + (num - 1)) > 0x270F)
  299. {
  300. if(addres == 0xFFFF && num == 1)
  301. {
  302. ;
  303. }
  304. else
  305. {
  306. return ModbusErrReply(0x03, ERR_OPE_ADDRES);
  307. }
  308. }
  309. /*操作数量超限*/
  310. if(num == 0 || num > 125)
  311. {
  312. return ModbusErrReply(0x03, ERR_DATA);
  313. }
  314. dataLen = num * 2;
  315. /*附加功能:读取0x10000寄存器*/
  316. if(ModbusExtPage[0] == 1 && addres == 0x0000)
  317. {
  318. /*将16位寄存器值拆分为两个8位*/
  319. readValH = (uint8_t)(ModbusExtReg[0] >> 8);
  320. readValL = (uint8_t)(ModbusExtReg[0] & 0x00FF);
  321. ModbusTxBuf[3] = readValH;
  322. ModbusTxBuf[4] = readValL;
  323. }
  324. /*附加功能:读取大量奇数寄存器*/
  325. else if(addres == 0xFFFF && num == 1)
  326. {
  327. return ModbusExtReadOdd(ModbusExtOdd[0]);
  328. }
  329. else
  330. {
  331. for(uint16_t i = 0; i < num; i++)
  332. {
  333. index = 3 + (i * 2);
  334. /*将16位寄存器值拆分为两个8位*/
  335. readValH = (uint8_t)(ModbusReg[addres + i] >> 8);
  336. readValL = (uint8_t)(ModbusReg[addres + i] & 0x00FF);
  337. ModbusTxBuf[index] = readValH;
  338. ModbusTxBuf[index + 1] = readValL;
  339. }
  340. }
  341. ModbusTxBuf[0] = SLAVE_ADDRES;
  342. ModbusTxBuf[1] = 0x03;
  343. ModbusTxBuf[2] = dataLen;
  344. AddCrc16(ModbusTxBuf, 3 + dataLen);
  345. ModbusTxLen = 5 + dataLen;
  346. return 0;
  347. }
  348. uint8_t ModbusWriteRegs(uint16_t addres, uint16_t num, uint8_t *data)
  349. {
  350. uint8_t index;
  351. uint8_t writeValH;
  352. uint8_t writeValL;
  353. uint16_t writeVal;
  354. if(ModbusRxLen < 11)
  355. {
  356. return ModbusErrReply(0x10, ERR_DATA);
  357. }
  358. /*操作地址超限*/
  359. if(addres > 0x270F || (addres + (num - 1)) > 0x270F)
  360. {
  361. if((addres == 0xFFFE || addres == 0xFFFF) && num == 1)
  362. {
  363. ;
  364. }
  365. else
  366. {
  367. return ModbusErrReply(0x10, ERR_OPE_ADDRES);
  368. }
  369. }
  370. /*操作数量超限*/
  371. if(num == 0 || num > 123)
  372. {
  373. return ModbusErrReply(0x10, ERR_DATA);
  374. }
  375. /*附加功能:读取0x10000寄存器*/
  376. if(addres == 0xFFFE && num == 1)
  377. {
  378. writeValH = data[0];
  379. writeValL = data[1];
  380. /*将要写入两个8位值拼接为16位*/
  381. writeVal = ((uint16_t)writeValH << 8) | ((uint16_t)writeValL & 0x00FF);
  382. ModbusExtPage[0] = writeVal;
  383. }
  384. /*附加功能:读取大量奇数寄存器*/
  385. else if(addres == 0xFFFF && num == 1)
  386. {
  387. writeValH = data[0];
  388. writeValL = data[1];
  389. /*将要写入两个8位值拼接为16位*/
  390. writeVal = ((uint16_t)writeValH << 8) | ((uint16_t)writeValL & 0x00FF);
  391. ModbusExtOdd[0] = writeVal;
  392. }
  393. /*正常功能*/
  394. else
  395. {
  396. for(uint16_t i = 0; i < num; i++)
  397. {
  398. index = i * 2;
  399. writeValH = data[index];
  400. writeValL = data[index + 1];
  401. /*将要写入两个8位值拼接为16位*/
  402. writeVal = ((uint16_t)writeValH << 8) | ((uint16_t)writeValL & 0x00FF);
  403. ModbusReg[addres + i] = writeVal;
  404. }
  405. }
  406. ModbusTxBuf[0] = SLAVE_ADDRES;
  407. ModbusTxBuf[1] = 0x10;
  408. /*操作地址*/
  409. ModbusTxBuf[2] = (uint8_t)(addres >> 8);
  410. ModbusTxBuf[3] = (uint8_t)(addres & 0x00FF);
  411. /*成功写入数量*/
  412. ModbusTxBuf[4] = (uint8_t)(num >> 8);
  413. ModbusTxBuf[5] = (uint8_t)(num & 0x00FF);
  414. AddCrc16(ModbusTxBuf, 6);
  415. ModbusTxLen = 8;
  416. return 0;
  417. }
  418. uint8_t ModbusWriteCoil(uint16_t addres, uint8_t *data)
  419. {
  420. uint16_t byteIndI;
  421. uint8_t bitIndI;
  422. uint16_t readVal;
  423. uint8_t writeVal;
  424. /*操作地址超限*/
  425. if(addres > 0x270F)
  426. {
  427. return ModbusErrReply(0x0F, ERR_OPE_ADDRES);
  428. }
  429. byteIndI = addres / 8;
  430. bitIndI = addres % 8;
  431. /*位掩码读取要写入的值*/
  432. readVal = ((uint16_t)data[0] << 8) | ((uint16_t)data[1] & 0x00FF);
  433. /*将写入值移位到要写入的位*/
  434. writeVal = (uint8_t)1 << bitIndI;
  435. /*置on*/
  436. if(readVal == 0xFF00)
  437. {
  438. ModbusCoil[byteIndI] |= writeVal;
  439. }
  440. /*置off*/
  441. else if(readVal == 0x0000)
  442. {
  443. ModbusCoil[byteIndI] &= (~writeVal);
  444. }
  445. else
  446. {
  447. return ModbusErrReply(0x05, ERR_DATA);
  448. }
  449. ModbusTxBuf[0] = SLAVE_ADDRES;
  450. ModbusTxBuf[1] = 0x0F;
  451. /*操作地址*/
  452. ModbusTxBuf[2] = (uint8_t)(addres >> 8);
  453. ModbusTxBuf[3] = (uint8_t)(addres & 0x00FF);
  454. /*成功写入*/
  455. ModbusTxBuf[4] = data[0];
  456. ModbusTxBuf[5] = data[1];
  457. AddCrc16(ModbusTxBuf, 6);
  458. ModbusTxLen = 8;
  459. return 0;
  460. }
  461. uint8_t ModbusWriteReg(uint16_t addres, uint8_t *data)
  462. {
  463. uint8_t writeValH;
  464. uint8_t writeValL;
  465. uint16_t writeVal;
  466. /*操作地址超限*/
  467. if(addres > 0x270F)
  468. {
  469. return ModbusErrReply(0x10, ERR_OPE_ADDRES);
  470. }
  471. writeValH = data[0];
  472. writeValL = data[1];
  473. /*将要写入两个8位值拼接为16位*/
  474. writeVal = ((uint16_t)writeValH << 8) | ((uint16_t)writeValL & 0x00FF);
  475. ModbusReg[addres] = writeVal;
  476. ModbusTxBuf[0] = SLAVE_ADDRES;
  477. ModbusTxBuf[1] = 0x10;
  478. /*操作地址*/
  479. ModbusTxBuf[2] = (uint8_t)(addres >> 8);
  480. ModbusTxBuf[3] = (uint8_t)(addres & 0x00FF);
  481. /*成功写入*/
  482. ModbusTxBuf[4] = writeValH;
  483. ModbusTxBuf[5] = writeValL;
  484. AddCrc16(ModbusTxBuf, 6);
  485. ModbusTxLen = 8;
  486. return 0;
  487. }
  488. uint8_t ModbusExtReadOdd(uint16_t num)
  489. {
  490. uint8_t i = 0;
  491. uint8_t numJ = (num + 124) / 125;
  492. uint8_t numI = num % 125;
  493. uint8_t index;
  494. uint16_t indexR;
  495. uint8_t readValH;
  496. uint8_t readValL;
  497. uint8_t dataLen;
  498. for(uint16_t j = 0; j < numJ; j++)
  499. {
  500. if(j == numJ - 1)
  501. {
  502. for(i = 0; i < numI; i++)
  503. {
  504. index = 3 + (i * 2);
  505. indexR = j * 250 + 2 * i + 1;
  506. /*将16位寄存器值拆分为两个8位*/
  507. readValH = (uint8_t)(ModbusReg[indexR] >> 8);
  508. readValL = (uint8_t)(ModbusReg[indexR] & 0x00FF);
  509. ModbusTxBuf[index] = readValH;
  510. ModbusTxBuf[index + 1] = readValL;
  511. }
  512. dataLen = 2 * numI;
  513. ModbusTxBuf[0] = SLAVE_ADDRES;
  514. ModbusTxBuf[1] = 0x03;
  515. ModbusTxBuf[2] = dataLen;
  516. AddCrc16(ModbusTxBuf, 3 + dataLen);
  517. ModbusTxLen = 5 + dataLen;
  518. }
  519. else
  520. {
  521. for(i = 0; i < 125; i++)
  522. {
  523. index = 3 + (i * 2);
  524. indexR = j * 250 + 2 * i + 1;
  525. /*将16位寄存器值拆分为两个8位*/
  526. readValH = (uint8_t)(ModbusReg[indexR] >> 8);
  527. readValL = (uint8_t)(ModbusReg[indexR] & 0x00FF);
  528. ModbusTxBuf[index] = readValH;
  529. ModbusTxBuf[index + 1] = readValL;
  530. }
  531. dataLen = 250;
  532. ModbusTxBuf[0] = SLAVE_ADDRES;
  533. ModbusTxBuf[1] = 0x03;
  534. ModbusTxBuf[2] = dataLen;
  535. AddCrc16(ModbusTxBuf, 3 + dataLen);
  536. ModbusTxLen = 5 + dataLen;
  537. }
  538. ModbusSend(ModbusTxBuf, ModbusTxLen);
  539. }
  540. return 0;
  541. }
  542. uint8_t ModbusErrReply(uint8_t func, uint8_t err)
  543. {
  544. ModbusTxBuf[0] = SLAVE_ADDRES;
  545. ModbusTxBuf[1] = func;
  546. ModbusTxBuf[2] = err;
  547. AddCrc16(ModbusTxBuf, 3);
  548. ModbusTxLen = 5;
  549. return err;
  550. }
  551. void AddCrc16(uint8_t *data, uint16_t length)
  552. {
  553. uint8_t *dataT = data;
  554. uint16_t crc16 = Crc16(data, length);
  555. /*低前高后*/
  556. dataT[length] = (uint8_t)(crc16 & 0x00FF);
  557. dataT[length + 1] = (uint8_t)(crc16 >> 8);
  558. }
  559. /*crc16校验*/
  560. uint16_t Crc16(const uint8_t *data, uint16_t length)
  561. {
  562. uint16_t crc;
  563. uint16_t byteInd;
  564. uint8_t bitInd;
  565. crc = 0xFFFFu;
  566. for (byteInd = 0u; byteInd < length; byteInd++)
  567. {
  568. crc ^= (uint16_t)data[byteInd];
  569. for (bitInd = 0u; bitInd < 8u; bitInd++)
  570. {
  571. if ((crc & 0x0001u) != 0u)
  572. {
  573. crc >>= 1;
  574. crc ^= 0xA001u;
  575. }
  576. else
  577. {
  578. crc >>= 1;
  579. }
  580. }
  581. }
  582. return crc;
  583. }
  584. /*crc16检查*/
  585. int8_t ChcekCrc16(uint16_t recCrc16, uint8_t *data, uint16_t length)
  586. {
  587. uint16_t crc16 = Crc16(data, (length - 2));
  588. if(recCrc16 == crc16)
  589. {
  590. return 0;
  591. }
  592. else
  593. {
  594. return -1;
  595. }
  596. }