Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

569 строки
15 KiB

  1. #include "stm32f4xx.h"
  2. #include "ucos_ii.h"
  3. #include "os.h"
  4. #include "string.h"
  5. #include "modbus_parse.h"
  6. #include "modbus_rec_send.h"
  7. extern OS_EVENT* ModbusWriteFlash; /*接收到modbus写入coil请求报文*/
  8. extern OS_EVENT* ModbusConnect; /*已接收到modbus正确报文*/
  9. uint8_t ModbusErr;
  10. /*0x270F + 1 = K10000 */
  11. uint8_t ModbusCoil[1250]; /*10000/8=1250*/
  12. uint16_t ModbusReg[10000];
  13. /*附加功能:页寄存器*/
  14. uint16_t ModbusExtPage[1] = {0}; /*设置地址为0xFFFE*/
  15. uint16_t ModbusExtReg[1]; /*地址映射为0x10000*/
  16. /*附加功能:读取所有单数个寄存器*/
  17. uint16_t ModbusExtOdd[1] = {0}; /*设置地址为0xFFFF*/
  18. uint8_t ModbusRxBuf[MODBUS_RX_BUF_SIZE]; /*接收数组*/
  19. uint16_t ModbusRxLen = 0; /*接收数据长度*/
  20. uint8_t ModbusTxBuf[MODBUS_TX_BUF_SIZE]; /*发送数组*/
  21. uint16_t ModbusTxLen = 0; /*发送数据长度*/
  22. /*modbus协议帧解析任务*/
  23. void AppTaskModbusParse (void *p_arg)
  24. {
  25. OS_ERR err;
  26. MODBUS_FRAME frame;
  27. uint16_t rxLen;
  28. uint8_t rxBuf[256];
  29. while(1)
  30. {
  31. /*无限期等待接收到数据帧信号量*/
  32. OSSemPend(ModbusReceived, 0, &err);
  33. /*数据接收,防止下一帧覆盖*/
  34. rxLen = ModbusRxLen;
  35. if(rxLen > MODBUS_RX_BUF_SIZE)
  36. {
  37. rxLen = 0;
  38. }
  39. memcpy(rxBuf, ModbusRxBuf, rxLen);
  40. /*帧分解*/
  41. frame.slaveAddres = rxBuf[0];
  42. frame.func = rxBuf[1];
  43. frame.crc = ((uint16_t)(rxBuf[rxLen - 2])) | ((uint16_t)rxBuf[rxLen - 1] << 8);
  44. frame.opeAddres = ((uint16_t)rxBuf[2] << 8) | ((uint16_t)rxBuf[3]);
  45. frame.opeNum = ((uint16_t)rxBuf[4] << 8) | ((uint16_t)rxBuf[5]);
  46. /*crc校验判断*/
  47. if(ChcekCrc16(frame.crc, rxBuf, rxLen) != 0)
  48. {
  49. /*crc校验错误,直接丢弃*/
  50. ModbusErr = ERR_CRC;
  51. continue;
  52. }
  53. /*从机地址判断*/
  54. if(frame.slaveAddres != SLAVE_ADDRES)
  55. {
  56. /*从机地址错误,直接丢弃*/
  57. ModbusErr = ERR_SLAVE_ADDRES;
  58. continue;
  59. }
  60. /*释放正确接收信号量*/
  61. OSSemPost(ModbusConnect);
  62. /*功能码分类*/
  63. switch(frame.func)
  64. {
  65. case 0x01:/*读线圈*/
  66. ModbusErr = ModbusReadCoils(frame.opeAddres, frame.opeNum);
  67. break;
  68. case 0x03:/*读寄存器*/
  69. ModbusErr = ModbusReadRegs(frame.opeAddres, frame.opeNum);
  70. break;
  71. case 0x0F:/*写多个线圈*/
  72. frame.wNum = rxBuf[6];
  73. memcpy(frame.wData, &rxBuf[7], frame.wNum);
  74. ModbusErr = ModbusWriteCoils(frame.opeAddres, frame.opeNum, frame.wData);
  75. break;
  76. case 0x10:/*写多个寄存器*/
  77. frame.wNum = rxBuf[6];
  78. memcpy(frame.wData, &rxBuf[7], frame.wNum);
  79. ModbusErr = ModbusWriteRegs(frame.opeAddres, frame.opeNum, frame.wData);
  80. break;
  81. case 0x05:/*写单个线圈*/
  82. memcpy(frame.wData, &rxBuf[4], 2);
  83. ModbusErr = ModbusWriteCoil(frame.opeAddres, frame.wData);
  84. break;
  85. case 0x06:/*写单个寄存器*/
  86. memcpy(frame.wData, &rxBuf[4], 2);
  87. ModbusErr = ModbusWriteReg(frame.opeAddres, frame.wData);
  88. break;
  89. default:/*功能码错误*/
  90. ModbusErr = ERR_FUNC;
  91. ModbusErr = ModbusErrReply(frame.func, ERR_FUNC);
  92. break;
  93. }
  94. /*实现附加功能时不在这里启动发送*/
  95. if(frame.func == 0x03 && frame.opeAddres == 0XFFFF);
  96. else
  97. {
  98. ModbusSend(ModbusTxBuf, ModbusTxLen);
  99. }
  100. if(ModbusErr == 0 && (frame.func == 0x0F || frame.func == 0x10
  101. || frame.func == 0x05 || frame.func == 0x06))
  102. {
  103. /*释放写FLASH信号量*/
  104. OSSemPost(ModbusWriteFlash);
  105. }
  106. }
  107. }
  108. uint8_t ModbusReadCoils(uint16_t addres, uint16_t num)
  109. {
  110. uint16_t byteIndI; /*字节索引*/
  111. uint8_t bitIndI; /*位索引*/
  112. uint16_t byteIndO;
  113. uint8_t bitIndO;
  114. uint8_t dataLen; /*响应帧返回字节数*/
  115. uint8_t index; /*发送数组索引*/
  116. uint8_t readVal; /*读取到的形式值*/
  117. uint8_t writeVal; /*写入的形式值*/
  118. if(ModbusRxLen < 8)
  119. {
  120. return ModbusErrReply(0x01, ERR_DATA);
  121. }
  122. /*操作地址超限*/
  123. if(addres > 0x270F || (addres + (num - 1)) > 0x270F)
  124. {
  125. return ModbusErrReply(0x01, ERR_OPE_ADDRES);
  126. }
  127. /*操作数量超限*/
  128. if(num == 0 || num > 2000)
  129. {
  130. return ModbusErrReply(0x01, ERR_DATA);
  131. }
  132. /*不能num/8+1,当为8的整数时会多一个*/
  133. dataLen = (num + 7) / 8;
  134. /*清零发送数组*/
  135. memset(&ModbusTxBuf[3], 0, 253);
  136. for(uint16_t i = 0; i < num; i++)
  137. {
  138. byteIndO = i / 8;
  139. bitIndO = i % 8;
  140. byteIndI = (addres + i) / 8;
  141. bitIndI = (addres + i) % 8;
  142. /*位掩码读取线圈值*/
  143. readVal = ModbusCoil[byteIndI] & ((uint8_t)1 << bitIndI);
  144. /*读取到的值为0则不进行操作*/
  145. if(readVal != 0)
  146. {
  147. index = 3 + byteIndO;
  148. /*将读取到的值移位到要写入的位*/
  149. writeVal = (uint8_t)1u << bitIndO;
  150. ModbusTxBuf[index] |= writeVal;
  151. }
  152. }
  153. ModbusTxBuf[0] = SLAVE_ADDRES; /*从机地址*/
  154. ModbusTxBuf[1] = 0x01; /*功能码*/
  155. ModbusTxBuf[2] = dataLen; /*响应帧返回数据字节数*/
  156. AddCrc16(ModbusTxBuf, 3 + dataLen);
  157. ModbusTxLen = 5 + dataLen;
  158. return 0;
  159. }
  160. uint8_t ModbusWriteCoils(uint16_t addres, uint16_t num, uint8_t *data)
  161. {
  162. uint16_t byteIndI;
  163. uint8_t bitIndI;
  164. uint16_t byteIndO;
  165. uint8_t bitIndO;
  166. uint8_t readVal;
  167. uint8_t writeVal;
  168. if(ModbusRxLen < 10)
  169. {
  170. return ModbusErrReply(0x0F, ERR_DATA);
  171. }
  172. /*操作地址超限*/
  173. if(addres > 0x270F || (addres + (num - 1)) > 0x270F)
  174. {
  175. return ModbusErrReply(0x0F, ERR_OPE_ADDRES);
  176. }
  177. /*操作数量超限*/
  178. if(num == 0 || num > 1968)
  179. {
  180. return ModbusErrReply(0x0F, ERR_DATA);
  181. }
  182. for(uint16_t i = 0; i < num; i++)
  183. {
  184. byteIndI = (addres + i) / 8;
  185. bitIndI = (addres + i) % 8;
  186. byteIndO = i / 8;
  187. bitIndO = i % 8;
  188. /*位掩码读取要写入的值*/
  189. readVal = data[byteIndO] & ((uint8_t)1 << bitIndO);
  190. /*将写入值移位到要写入的位*/
  191. writeVal = (uint8_t)1 << bitIndI;
  192. /*对应位写入1*/
  193. if(readVal != 0)
  194. {
  195. ModbusCoil[byteIndI] |= writeVal;
  196. }
  197. /*对应位写入0*/
  198. else
  199. {
  200. ModbusCoil[byteIndI] &= (~writeVal);
  201. }
  202. }
  203. ModbusTxBuf[0] = SLAVE_ADDRES;
  204. ModbusTxBuf[1] = 0x0F;
  205. /*操作地址*/
  206. ModbusTxBuf[2] = (uint8_t)(addres >> 8);
  207. ModbusTxBuf[3] = (uint8_t)(addres & 0x00FF);
  208. /*成功写入的数量*/
  209. ModbusTxBuf[4] = (uint8_t)(num >> 8);
  210. ModbusTxBuf[5] = (uint8_t)(num & 0x00FF);
  211. AddCrc16(ModbusTxBuf, 6);
  212. ModbusTxLen = 8;
  213. return 0;
  214. }
  215. uint8_t ModbusReadRegs(uint16_t addres, uint16_t num)
  216. {
  217. uint8_t index;
  218. uint8_t readValH;
  219. uint8_t readValL;
  220. uint8_t dataLen;
  221. if(ModbusRxLen < 8)
  222. {
  223. return ModbusErrReply(0x03, ERR_DATA);
  224. }
  225. /*操作地址超限*/
  226. if(addres > 0x270F || (addres + (num - 1)) > 0x270F)
  227. {
  228. if(addres == 0xFFFF && num == 1)
  229. {
  230. ;
  231. }
  232. else
  233. {
  234. return ModbusErrReply(0x03, ERR_OPE_ADDRES);
  235. }
  236. }
  237. /*操作数量超限*/
  238. if(num == 0 || num > 125)
  239. {
  240. return ModbusErrReply(0x03, ERR_DATA);
  241. }
  242. dataLen = num * 2;
  243. /*附加功能:读取0x10000寄存器*/
  244. if(ModbusExtPage[0] == 1 && addres == 0x0000)
  245. {
  246. /*将16位寄存器值拆分为两个8位*/
  247. readValH = (uint8_t)(ModbusExtReg[0] >> 8);
  248. readValL = (uint8_t)(ModbusExtReg[0] & 0x00FF);
  249. ModbusTxBuf[3] = readValH;
  250. ModbusTxBuf[4] = readValL;
  251. }
  252. /*附加功能:读取大量奇数寄存器*/
  253. else if(addres == 0xFFFF && num == 1)
  254. {
  255. return ModbusExtReadOdd(ModbusExtOdd[0]);
  256. }
  257. else
  258. {
  259. for(uint16_t i = 0; i < num; i++)
  260. {
  261. index = 3 + (i * 2);
  262. /*将16位寄存器值拆分为两个8位*/
  263. readValH = (uint8_t)(ModbusReg[addres + i] >> 8);
  264. readValL = (uint8_t)(ModbusReg[addres + i] & 0x00FF);
  265. ModbusTxBuf[index] = readValH;
  266. ModbusTxBuf[index + 1] = readValL;
  267. }
  268. }
  269. ModbusTxBuf[0] = SLAVE_ADDRES;
  270. ModbusTxBuf[1] = 0x03;
  271. ModbusTxBuf[2] = dataLen;
  272. AddCrc16(ModbusTxBuf, 3 + dataLen);
  273. ModbusTxLen = 5 + dataLen;
  274. return 0;
  275. }
  276. uint8_t ModbusWriteRegs(uint16_t addres, uint16_t num, uint8_t *data)
  277. {
  278. uint8_t index;
  279. uint8_t writeValH;
  280. uint8_t writeValL;
  281. uint16_t writeVal;
  282. if(ModbusRxLen < 11)
  283. {
  284. return ModbusErrReply(0x10, ERR_DATA);
  285. }
  286. /*操作地址超限*/
  287. if(addres > 0x270F || (addres + (num - 1)) > 0x270F)
  288. {
  289. if((addres == 0xFFFE || addres == 0xFFFF) && num == 1)
  290. {
  291. ;
  292. }
  293. else
  294. {
  295. return ModbusErrReply(0x10, ERR_OPE_ADDRES);
  296. }
  297. }
  298. /*操作数量超限*/
  299. if(num == 0 || num > 123)
  300. {
  301. return ModbusErrReply(0x10, ERR_DATA);
  302. }
  303. /*附加功能:读取0x10000寄存器*/
  304. if(addres == 0xFFFE && num == 1)
  305. {
  306. writeValH = data[0];
  307. writeValL = data[1];
  308. /*将要写入两个8位值拼接为16位*/
  309. writeVal = ((uint16_t)writeValH << 8) | ((uint16_t)writeValL & 0x00FF);
  310. ModbusExtPage[0] = writeVal;
  311. }
  312. /*附加功能:读取大量奇数寄存器*/
  313. else if(addres == 0xFFFF && num == 1)
  314. {
  315. writeValH = data[0];
  316. writeValL = data[1];
  317. /*将要写入两个8位值拼接为16位*/
  318. writeVal = ((uint16_t)writeValH << 8) | ((uint16_t)writeValL & 0x00FF);
  319. ModbusExtOdd[0] = writeVal;
  320. }
  321. /*正常功能*/
  322. else
  323. {
  324. for(uint16_t i = 0; i < num; i++)
  325. {
  326. index = i * 2;
  327. writeValH = data[index];
  328. writeValL = data[index + 1];
  329. /*将要写入两个8位值拼接为16位*/
  330. writeVal = ((uint16_t)writeValH << 8) | ((uint16_t)writeValL & 0x00FF);
  331. ModbusReg[addres + i] = writeVal;
  332. }
  333. }
  334. ModbusTxBuf[0] = SLAVE_ADDRES;
  335. ModbusTxBuf[1] = 0x10;
  336. /*操作地址*/
  337. ModbusTxBuf[2] = (uint8_t)(addres >> 8);
  338. ModbusTxBuf[3] = (uint8_t)(addres & 0x00FF);
  339. /*成功写入数量*/
  340. ModbusTxBuf[4] = (uint8_t)(num >> 8);
  341. ModbusTxBuf[5] = (uint8_t)(num & 0x00FF);
  342. AddCrc16(ModbusTxBuf, 6);
  343. ModbusTxLen = 8;
  344. return 0;
  345. }
  346. uint8_t ModbusWriteCoil(uint16_t addres, uint8_t *data)
  347. {
  348. uint16_t byteIndI;
  349. uint8_t bitIndI;
  350. uint16_t readVal;
  351. uint8_t writeVal;
  352. if(ModbusRxLen < 8)
  353. {
  354. return ModbusErrReply(0x05, ERR_DATA);
  355. }
  356. /*操作地址超限*/
  357. if(addres > 0x270F)
  358. {
  359. return ModbusErrReply(0x05, ERR_OPE_ADDRES);
  360. }
  361. byteIndI = addres / 8;
  362. bitIndI = addres % 8;
  363. /*位掩码读取要写入的值*/
  364. readVal = ((uint16_t)data[0] << 8) | ((uint16_t)data[1] & 0x00FF);
  365. /*将写入值移位到要写入的位*/
  366. writeVal = (uint8_t)1 << bitIndI;
  367. /*置on*/
  368. if(readVal == 0xFF00)
  369. {
  370. ModbusCoil[byteIndI] |= writeVal;
  371. }
  372. /*置off*/
  373. else if(readVal == 0x0000)
  374. {
  375. ModbusCoil[byteIndI] &= (~writeVal);
  376. }
  377. else
  378. {
  379. return ModbusErrReply(0x05, ERR_DATA);
  380. }
  381. ModbusTxBuf[0] = SLAVE_ADDRES;
  382. ModbusTxBuf[1] = 0x05;
  383. /*操作地址*/
  384. ModbusTxBuf[2] = (uint8_t)(addres >> 8);
  385. ModbusTxBuf[3] = (uint8_t)(addres & 0x00FF);
  386. /*成功写入*/
  387. ModbusTxBuf[4] = data[0];
  388. ModbusTxBuf[5] = data[1];
  389. AddCrc16(ModbusTxBuf, 6);
  390. ModbusTxLen = 8;
  391. return 0;
  392. }
  393. uint8_t ModbusWriteReg(uint16_t addres, uint8_t *data)
  394. {
  395. uint8_t writeValH;
  396. uint8_t writeValL;
  397. uint16_t writeVal;
  398. if(ModbusRxLen < 8)
  399. {
  400. return ModbusErrReply(0x06, ERR_DATA);
  401. }
  402. /*操作地址超限*/
  403. if(addres > 0x270F)
  404. {
  405. return ModbusErrReply(0x06, ERR_OPE_ADDRES);
  406. }
  407. writeValH = data[0];
  408. writeValL = data[1];
  409. /*将要写入两个8位值拼接为16位*/
  410. writeVal = ((uint16_t)writeValH << 8) | ((uint16_t)writeValL & 0x00FF);
  411. ModbusReg[addres] = writeVal;
  412. ModbusTxBuf[0] = SLAVE_ADDRES;
  413. ModbusTxBuf[1] = 0x06;
  414. /*操作地址*/
  415. ModbusTxBuf[2] = (uint8_t)(addres >> 8);
  416. ModbusTxBuf[3] = (uint8_t)(addres & 0x00FF);
  417. /*成功写入*/
  418. ModbusTxBuf[4] = writeValH;
  419. ModbusTxBuf[5] = writeValL;
  420. AddCrc16(ModbusTxBuf, 6);
  421. ModbusTxLen = 8;
  422. return 0;
  423. }
  424. uint8_t ModbusExtReadOdd(uint16_t num)
  425. {
  426. uint8_t i = 0;
  427. uint8_t numJ = (num + 124) / 125;
  428. uint8_t numI = num % 125;
  429. uint8_t index;
  430. uint16_t indexR;
  431. uint8_t readValH;
  432. uint8_t readValL;
  433. uint8_t dataLen;
  434. for(uint16_t j = 0; j < numJ; j++)
  435. {
  436. if(j == numJ - 1)
  437. {
  438. for(i = 0; i < numI; i++)
  439. {
  440. index = 3 + (i * 2);
  441. indexR = j * 250 + 2 * i + 1;
  442. /*将16位寄存器值拆分为两个8位*/
  443. readValH = (uint8_t)(ModbusReg[indexR] >> 8);
  444. readValL = (uint8_t)(ModbusReg[indexR] & 0x00FF);
  445. ModbusTxBuf[index] = readValH;
  446. ModbusTxBuf[index + 1] = readValL;
  447. }
  448. dataLen = 2 * numI;
  449. ModbusTxBuf[0] = SLAVE_ADDRES;
  450. ModbusTxBuf[1] = 0x03;
  451. ModbusTxBuf[2] = dataLen;
  452. AddCrc16(ModbusTxBuf, 3 + dataLen);
  453. ModbusTxLen = 5 + dataLen;
  454. }
  455. else
  456. {
  457. for(i = 0; i < 125; i++)
  458. {
  459. index = 3 + (i * 2);
  460. indexR = j * 250 + 2 * i + 1;
  461. /*将16位寄存器值拆分为两个8位*/
  462. readValH = (uint8_t)(ModbusReg[indexR] >> 8);
  463. readValL = (uint8_t)(ModbusReg[indexR] & 0x00FF);
  464. ModbusTxBuf[index] = readValH;
  465. ModbusTxBuf[index + 1] = readValL;
  466. }
  467. dataLen = 250;
  468. ModbusTxBuf[0] = SLAVE_ADDRES;
  469. ModbusTxBuf[1] = 0x03;
  470. ModbusTxBuf[2] = dataLen;
  471. AddCrc16(ModbusTxBuf, 3 + dataLen);
  472. ModbusTxLen = 5 + dataLen;
  473. }
  474. /*演示2ms*/
  475. OSTimeDly(OS_TICKS_PER_SEC / 500);
  476. ModbusSend(ModbusTxBuf, ModbusTxLen);
  477. }
  478. return 0;
  479. }
  480. uint8_t ModbusErrReply(uint8_t func, uint8_t err)
  481. {
  482. ModbusTxBuf[0] = SLAVE_ADDRES;
  483. ModbusTxBuf[1] = func | 0x80;
  484. ModbusTxBuf[2] = err;
  485. AddCrc16(ModbusTxBuf, 3);
  486. ModbusTxLen = 5;
  487. return err;
  488. }