modbus.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. #include "mmodbus.h"
  2. #include "usart.h"
  3. #include "timer.h"
  4. #include "log.h"
  5. #include "led.h"
  6. MModBus_t mmodbus;
  7. // #####################################################################################################
  8. #if (_MMODBUS_RTU == 1)
  9. static const uint16_t wCRCTable[] =
  10. {
  11. 0X0000, 0XC0C1, 0XC181, 0X0140, 0XC301, 0X03C0, 0X0280, 0XC241,
  12. 0XC601, 0X06C0, 0X0780, 0XC741, 0X0500, 0XC5C1, 0XC481, 0X0440,
  13. 0XCC01, 0X0CC0, 0X0D80, 0XCD41, 0X0F00, 0XCFC1, 0XCE81, 0X0E40,
  14. 0X0A00, 0XCAC1, 0XCB81, 0X0B40, 0XC901, 0X09C0, 0X0880, 0XC841,
  15. 0XD801, 0X18C0, 0X1980, 0XD941, 0X1B00, 0XDBC1, 0XDA81, 0X1A40,
  16. 0X1E00, 0XDEC1, 0XDF81, 0X1F40, 0XDD01, 0X1DC0, 0X1C80, 0XDC41,
  17. 0X1400, 0XD4C1, 0XD581, 0X1540, 0XD701, 0X17C0, 0X1680, 0XD641,
  18. 0XD201, 0X12C0, 0X1380, 0XD341, 0X1100, 0XD1C1, 0XD081, 0X1040,
  19. 0XF001, 0X30C0, 0X3180, 0XF141, 0X3300, 0XF3C1, 0XF281, 0X3240,
  20. 0X3600, 0XF6C1, 0XF781, 0X3740, 0XF501, 0X35C0, 0X3480, 0XF441,
  21. 0X3C00, 0XFCC1, 0XFD81, 0X3D40, 0XFF01, 0X3FC0, 0X3E80, 0XFE41,
  22. 0XFA01, 0X3AC0, 0X3B80, 0XFB41, 0X3900, 0XF9C1, 0XF881, 0X3840,
  23. 0X2800, 0XE8C1, 0XE981, 0X2940, 0XEB01, 0X2BC0, 0X2A80, 0XEA41,
  24. 0XEE01, 0X2EC0, 0X2F80, 0XEF41, 0X2D00, 0XEDC1, 0XEC81, 0X2C40,
  25. 0XE401, 0X24C0, 0X2580, 0XE541, 0X2700, 0XE7C1, 0XE681, 0X2640,
  26. 0X2200, 0XE2C1, 0XE381, 0X2340, 0XE101, 0X21C0, 0X2080, 0XE041,
  27. 0XA001, 0X60C0, 0X6180, 0XA141, 0X6300, 0XA3C1, 0XA281, 0X6240,
  28. 0X6600, 0XA6C1, 0XA781, 0X6740, 0XA501, 0X65C0, 0X6480, 0XA441,
  29. 0X6C00, 0XACC1, 0XAD81, 0X6D40, 0XAF01, 0X6FC0, 0X6E80, 0XAE41,
  30. 0XAA01, 0X6AC0, 0X6B80, 0XAB41, 0X6900, 0XA9C1, 0XA881, 0X6840,
  31. 0X7800, 0XB8C1, 0XB981, 0X7940, 0XBB01, 0X7BC0, 0X7A80, 0XBA41,
  32. 0XBE01, 0X7EC0, 0X7F80, 0XBF41, 0X7D00, 0XBDC1, 0XBC81, 0X7C40,
  33. 0XB401, 0X74C0, 0X7580, 0XB541, 0X7700, 0XB7C1, 0XB681, 0X7640,
  34. 0X7200, 0XB2C1, 0XB381, 0X7340, 0XB101, 0X71C0, 0X7080, 0XB041,
  35. 0X5000, 0X90C1, 0X9181, 0X5140, 0X9301, 0X53C0, 0X5280, 0X9241,
  36. 0X9601, 0X56C0, 0X5780, 0X9741, 0X5500, 0X95C1, 0X9481, 0X5440,
  37. 0X9C01, 0X5CC0, 0X5D80, 0X9D41, 0X5F00, 0X9FC1, 0X9E81, 0X5E40,
  38. 0X5A00, 0X9AC1, 0X9B81, 0X5B40, 0X9901, 0X59C0, 0X5880, 0X9841,
  39. 0X8801, 0X48C0, 0X4980, 0X8941, 0X4B00, 0X8BC1, 0X8A81, 0X4A40,
  40. 0X4E00, 0X8EC1, 0X8F81, 0X4F40, 0X8D01, 0X4DC0, 0X4C80, 0X8C41,
  41. 0X4400, 0X84C1, 0X8581, 0X4540, 0X8701, 0X47C0, 0X4680, 0X8641,
  42. 0X8201, 0X42C0, 0X4380, 0X8341, 0X4100, 0X81C1, 0X8081, 0X4040};
  43. // crc校验
  44. uint16_t mmodbus_crc16(const uint8_t *nData, uint16_t wLength)
  45. {
  46. uint8_t nTemp;
  47. uint16_t wCRCWord = 0xFFFF;
  48. while (wLength--)
  49. {
  50. nTemp = *nData++ ^ wCRCWord;
  51. wCRCWord >>= 8;
  52. wCRCWord ^= wCRCTable[nTemp];
  53. }
  54. return wCRCWord;
  55. }
  56. #endif
  57. void mmodbus_callback(UART_HandleTypeDef *husart)
  58. {
  59. if(__HAL_UART_GET_FLAG(husart, UART_FLAG_RXNE) && __HAL_UART_GET_IT_SOURCE(husart, UART_IT_RXNE))
  60. {
  61. if (mmodbus.rxIndex < _MMODBUS_RXSIZE - 1)
  62. {
  63. mmodbus.rxBuf[mmodbus.rxIndex] = husart->Instance->DR;
  64. mmodbus.rxIndex++;
  65. }
  66. else
  67. {
  68. uint8_t data = husart->Instance->DR;
  69. }
  70. }
  71. if ((mmodbus.rxIndex > 0) && RESET != __HAL_UART_GET_FLAG(husart, USART_FLAG_IDLE) && __HAL_UART_GET_IT_SOURCE(husart, UART_IT_IDLE))
  72. {
  73. uint8_t i;
  74. mmodbus.done = 1;
  75. i = husart->Instance->SR;
  76. i = husart->Instance->DR;
  77. return;
  78. }
  79. mmodbus.rxTime = gettick();
  80. }
  81. // ##################################################################################################
  82. uint16_t mmodbus_receiveRaw(uint32_t timeout)
  83. {
  84. uint32_t startTime = gettick();
  85. while (1)
  86. {
  87. if (gettick() - startTime> timeout * 1000)
  88. return 0;
  89. if (mmodbus.done == 1)
  90. {
  91. return mmodbus.rxIndex;
  92. }
  93. mmodbus_delay(5);
  94. }
  95. }
  96. // ##################################################################################################
  97. bool mmodbus_sendRaw(uint8_t *data, uint16_t size, uint32_t timeout)
  98. {
  99. while(mmodbus.txBusy == 1)
  100. mmodbus_delay(1);
  101. mmodbus.txBusy = 1;
  102. memset(mmodbus.rxBuf, 0, _MMODBUS_RXSIZE);
  103. mmodbus.rxIndex = 0;
  104. mmodbus.done = 0;
  105. uint32_t startTime = gettick();
  106. portENTER_CRITICAL();
  107. USART_485_Send(data,size);
  108. portEXIT_CRITICAL();
  109. mmodbus.done=0;
  110. mmodbus.txBusy = 0;
  111. return true;
  112. }
  113. // ##################################################################################################
  114. bool mmodbus_init(uint32_t timeout)
  115. {
  116. // HAL_GPIO_WritePin(_MMODBUS_CTRL_GPIO, _MMODBUS_CTRL_PIN, GPIO_PIN_RESET); 此处初始化在485 init过
  117. HAL_GPIO_WritePin(_MMODBUS_CTRL_GPIO, _MMODBUS_CTRL_PIN,0);
  118. memset(&mmodbus, 0, sizeof(mmodbus));
  119. mmodbus.timeout = timeout;
  120. return true;
  121. }
  122. // ##################################################################################################
  123. void mmodbus_set16bitOrder(MModBus_16bitOrder_t MModBus_16bitOrder_)
  124. {
  125. mmodbus.byteOrder16 = MModBus_16bitOrder_;
  126. }
  127. // ##################################################################################################
  128. void mmodbus_set32bitOrder(MModBus_32bitOrder_t MModBus_32bitOrder_)
  129. {
  130. mmodbus.byteOrder32 = MModBus_32bitOrder_;
  131. }
  132. // ##################################################################################################
  133. bool mmodbus_readCoil(uint8_t slaveAddress, uint16_t number, uint8_t *data)
  134. {
  135. return mmodbus_readCoils(slaveAddress, number, 1, data);
  136. }
  137. // ##################################################################################################
  138. // 读线圈
  139. bool mmodbus_readCoils(uint8_t slaveAddress, uint16_t startnumber, uint16_t length, uint8_t *data)
  140. {
  141. #if (_MMODBUS_RTU == 1)
  142. uint8_t txData[8];
  143. txData[0] = slaveAddress;
  144. txData[1] = MModbusCMD_ReadCoilStatus;
  145. txData[2] = (startnumber & 0xFF00) >> 8;
  146. txData[3] = (startnumber & 0x00FF);
  147. txData[4] = (length & 0xFF00) >> 8;
  148. txData[5] = (length & 0x00FF);
  149. static uint16_t crc;
  150. crc = mmodbus_crc16(txData, 6);
  151. txData[6] = (crc & 0x00FF);
  152. txData[7] = (crc & 0xFF00) >> 8;
  153. mmodbus_sendRaw(txData, 8, 100);
  154. uint16_t recLen = mmodbus_receiveRaw(mmodbus.timeout);
  155. if (recLen == 0)
  156. return false;
  157. if (mmodbus.rxBuf[0] != slaveAddress)
  158. return false;
  159. if (mmodbus.rxBuf[1] != MModbusCMD_ReadCoilStatus)
  160. return false;
  161. crc = mmodbus_crc16(mmodbus.rxBuf, mmodbus.rxBuf[2] + 3);
  162. if (((crc & 0x00FF) != mmodbus.rxBuf[mmodbus.rxBuf[2] + 3]) || (((crc & 0xFF00) >> 8) != mmodbus.rxBuf[mmodbus.rxBuf[2] + 4]))
  163. return false;
  164. if (data != NULL)
  165. memcpy(data, &mmodbus.rxBuf[3], mmodbus.rxBuf[2]);
  166. return true;
  167. #endif
  168. #if (_MMODBUS_ASCII == 1)
  169. #endif
  170. }
  171. // ##################################################################################################
  172. bool mmodbus_readDiscreteInput(uint8_t slaveAddress, uint16_t number, uint8_t *data)
  173. {
  174. return mmodbus_readDiscreteInputs(slaveAddress, number, 1, data);
  175. }
  176. // ##################################################################################################
  177. // 读取线圈功能码处理
  178. bool mmodbus_readDiscreteInputs(uint8_t slaveAddress, uint16_t startnumber, uint16_t length, uint8_t *data)
  179. {
  180. #if (_MMODBUS_RTU == 1)
  181. uint8_t txData[8];
  182. txData[0] = slaveAddress;
  183. txData[1] = MModbusCMD_ReadDiscreteInputs;
  184. txData[2] = (startnumber & 0xFF00) >> 8;
  185. txData[3] = (startnumber & 0x00FF);
  186. txData[4] = (length & 0xFF00) >> 8;
  187. txData[5] = (length & 0x00FF);
  188. static uint16_t crc;
  189. crc = mmodbus_crc16(txData, 6);
  190. txData[6] = (crc & 0x00FF);
  191. txData[7] = (crc & 0xFF00) >> 8;
  192. mmodbus_sendRaw(txData, 8, 100);
  193. uint16_t recLen = mmodbus_receiveRaw(mmodbus.timeout);
  194. if (recLen == 0)
  195. return false;
  196. if (mmodbus.rxBuf[0] != slaveAddress)
  197. return false;
  198. if (mmodbus.rxBuf[1] != MModbusCMD_ReadDiscreteInputs)
  199. return false;
  200. crc = mmodbus_crc16(mmodbus.rxBuf, mmodbus.rxBuf[2] + 3);
  201. if (((crc & 0x00FF) != mmodbus.rxBuf[mmodbus.rxBuf[2] + 3]) || (((crc & 0xFF00) >> 8) != mmodbus.rxBuf[mmodbus.rxBuf[2] + 4]))
  202. return false;
  203. if (data != NULL)
  204. memcpy(data, &mmodbus.rxBuf[3], mmodbus.rxBuf[2]);
  205. return true;
  206. #endif
  207. }
  208. // ##################################################################################################
  209. bool mmodbus_readInputRegisters8i(uint8_t slaveAddress, uint16_t startnumber, uint16_t length, uint8_t *data)
  210. {
  211. #if (_MMODBUS_RTU == 1)
  212. uint8_t txData[8];
  213. txData[0] = slaveAddress;
  214. txData[1] = MModbusCMD_ReadInputRegisters;
  215. txData[2] = (startnumber & 0xFF00) >> 8;
  216. txData[3] = (startnumber & 0x00FF);
  217. txData[4] = (length & 0xFF00) >> 8;
  218. txData[5] = (length & 0x00FF);
  219. static uint16_t crc;
  220. crc = mmodbus_crc16(txData, 6);
  221. txData[6] = (crc & 0x00FF);
  222. txData[7] = (crc & 0xFF00) >> 8;
  223. mmodbus_sendRaw(txData, 8, 100);
  224. uint16_t recLen = mmodbus_receiveRaw(mmodbus.timeout);
  225. if (recLen == 0)
  226. return false;
  227. if (mmodbus.rxBuf[0] != slaveAddress)
  228. return false;
  229. if (mmodbus.rxBuf[1] != MModbusCMD_ReadInputRegisters)
  230. return false;
  231. crc = mmodbus_crc16(mmodbus.rxBuf, mmodbus.rxBuf[2] + 3);
  232. if (((crc & 0x00FF) != mmodbus.rxBuf[mmodbus.rxBuf[2] + 3]) || (((crc & 0xFF00) >> 8) != mmodbus.rxBuf[mmodbus.rxBuf[2] + 4]))
  233. return false;
  234. if (data != NULL)
  235. memcpy(data, &mmodbus.rxBuf[3], mmodbus.rxBuf[2]);
  236. return true;
  237. #endif
  238. }
  239. // ##################################################################################################
  240. bool mmodbus_readInputRegister32f(uint8_t slaveAddress, uint16_t number, float *data)
  241. {
  242. return mmodbus_readInputRegisters32f(slaveAddress, number, 1, data);
  243. }
  244. // ##################################################################################################
  245. bool mmodbus_readInputRegisters32f(uint8_t slaveAddress, uint16_t startnumber, uint16_t length, float *data)
  246. {
  247. bool ret = mmodbus_readInputRegisters8i(slaveAddress, startnumber, length * 2, (uint8_t *)data);
  248. if (ret == true)
  249. {
  250. for (uint16_t i = 0; i < length; i++)
  251. {
  252. uint8_t tmp1[4], tmp2[4];
  253. switch (mmodbus.byteOrder32)
  254. {
  255. case MModBus_32bitOrder_DCBA:
  256. memcpy(tmp1, &data[i], 4);
  257. tmp2[0] = tmp1[3];
  258. tmp2[1] = tmp1[2];
  259. tmp2[2] = tmp1[1];
  260. tmp2[3] = tmp1[0];
  261. memcpy(&data[i], tmp2, 4);
  262. break;
  263. case MModBus_32bitOrder_BADC:
  264. memcpy(tmp1, &data[i], 4);
  265. tmp2[0] = tmp1[1];
  266. tmp2[1] = tmp1[0];
  267. tmp2[2] = tmp1[3];
  268. tmp2[3] = tmp1[2];
  269. memcpy(&data[i], tmp2, 4);
  270. break;
  271. case MModBus_32bitOrder_CDAB:
  272. memcpy(tmp1, &data[i], 4);
  273. tmp2[0] = tmp1[2];
  274. tmp2[1] = tmp1[3];
  275. tmp2[2] = tmp1[0];
  276. tmp2[3] = tmp1[1];
  277. memcpy(&data[i], tmp2, 4);
  278. break;
  279. default:
  280. break;
  281. }
  282. }
  283. return true;
  284. }
  285. else
  286. return false;
  287. }
  288. // ##################################################################################################
  289. bool mmodbus_readInputRegister32i(uint8_t slaveAddress, uint16_t number, uint32_t *data)
  290. {
  291. return mmodbus_readInputRegisters32i(slaveAddress, number, 1, data);
  292. }
  293. // ##################################################################################################
  294. bool mmodbus_readInputRegisters32i(uint8_t slaveAddress, uint16_t startnumber, uint16_t length, uint32_t *data)
  295. {
  296. return mmodbus_readInputRegisters32f(slaveAddress, startnumber, length, (float *)data);
  297. }
  298. // ##################################################################################################
  299. bool mmodbus_readInputRegister16i(uint8_t slaveAddress, uint16_t number, uint16_t *data)
  300. {
  301. return mmodbus_readInputRegisters16i(slaveAddress, number, 1, data);
  302. }
  303. // ##################################################################################################
  304. bool mmodbus_readInputRegisters16i(uint8_t slaveAddress, uint16_t startnumber, uint16_t length, uint16_t *data)
  305. {
  306. bool ret = mmodbus_readInputRegisters8i(slaveAddress, startnumber, length * 1, (uint8_t *)data);
  307. if (ret == true)
  308. {
  309. uint8_t tmp1[2], tmp2[2];
  310. for (uint16_t i = 0; i < length; i++)
  311. {
  312. switch (mmodbus.byteOrder16)
  313. {
  314. case MModBus_16bitOrder_AB:
  315. memcpy(tmp1, &data[i], 2);
  316. tmp2[0] = tmp1[0];
  317. tmp2[1] = tmp1[1];
  318. memcpy(&data[i], tmp2, 2);
  319. break;
  320. default:
  321. memcpy(tmp1, &data[i], 2);
  322. tmp2[0] = tmp1[1];
  323. tmp2[1] = tmp1[0];
  324. memcpy(&data[i], tmp2, 2);
  325. break;
  326. }
  327. }
  328. return true;
  329. }
  330. else
  331. return false;
  332. }
  333. // ##################################################################################################
  334. bool mmodbus_readHoldingRegisters8i(uint8_t slaveAddress, uint16_t startnumber, uint16_t length, uint8_t *data)
  335. {
  336. #if (_MMODBUS_RTU == 1)
  337. uint8_t txData[8];
  338. txData[0] = slaveAddress;
  339. txData[1] = MModbusCMD_ReadHoldingRegisters;
  340. txData[2] = (startnumber & 0xFF00) >> 8;
  341. txData[3] = (startnumber & 0x00FF);
  342. txData[4] = (length & 0xFF00) >> 8;
  343. txData[5] = (length & 0x00FF);
  344. static uint16_t crc;
  345. crc = mmodbus_crc16(txData, 6);
  346. txData[6] = (crc & 0x00FF);
  347. txData[7] = (crc & 0xFF00) >> 8;
  348. mmodbus_sendRaw(txData, 8, 100);
  349. uint16_t recLen = mmodbus_receiveRaw(mmodbus.timeout);
  350. if (recLen == 0)
  351. return false;
  352. if (mmodbus.rxBuf[0] != slaveAddress)
  353. return false;
  354. if (mmodbus.rxBuf[1] != MModbusCMD_ReadHoldingRegisters)
  355. return false;
  356. crc = mmodbus_crc16(mmodbus.rxBuf, mmodbus.rxBuf[2] + 3);
  357. if (((crc & 0x00FF) != mmodbus.rxBuf[mmodbus.rxBuf[2] + 3]) || (((crc & 0xFF00) >> 8) != mmodbus.rxBuf[mmodbus.rxBuf[2] + 4]))
  358. return false;
  359. if (data != NULL)
  360. {
  361. for (uint8_t i = 0; i < mmodbus.rxBuf[2]; i += 2)
  362. {
  363. uint8_t H = mmodbus.rxBuf[i + 3];
  364. mmodbus.rxBuf[i + 3] = mmodbus.rxBuf[i + 3 + 1];
  365. mmodbus.rxBuf[i + 3 + 1] = H;
  366. }
  367. memcpy(data, &mmodbus.rxBuf[3], mmodbus.rxBuf[2]);
  368. }
  369. return true;
  370. #endif
  371. }
  372. // ##################################################################################################
  373. bool mmodbus_readHoldingRegister32f(uint8_t slaveAddress, uint16_t number, float *data)
  374. {
  375. return mmodbus_readHoldingRegisters32f(slaveAddress, number, 1, data);
  376. }
  377. // ##################################################################################################
  378. bool mmodbus_readHoldingRegisters32f(uint8_t slaveAddress, uint16_t startnumber, uint16_t length, float *data)
  379. {
  380. bool ret = mmodbus_readHoldingRegisters8i(slaveAddress, startnumber, length * 2, (uint8_t *)data);
  381. if (ret == true)
  382. {
  383. for (uint16_t i = 0; i < length; i++)
  384. {
  385. uint8_t tmp1[4], tmp2[4];
  386. switch (mmodbus.byteOrder32)
  387. {
  388. case MModBus_32bitOrder_DCBA:
  389. memcpy(tmp1, &data[i], 4);
  390. tmp2[0] = tmp1[3];
  391. tmp2[1] = tmp1[2];
  392. tmp2[2] = tmp1[1];
  393. tmp2[3] = tmp1[0];
  394. memcpy(&data[i], tmp2, 4);
  395. break;
  396. case MModBus_32bitOrder_BADC:
  397. memcpy(tmp1, &data[i], 4);
  398. tmp2[0] = tmp1[1];
  399. tmp2[1] = tmp1[0];
  400. tmp2[2] = tmp1[3];
  401. tmp2[3] = tmp1[2];
  402. memcpy(&data[i], tmp2, 4);
  403. break;
  404. case MModBus_32bitOrder_CDAB:
  405. memcpy(tmp1, &data[i], 4);
  406. tmp2[0] = tmp1[2];
  407. tmp2[1] = tmp1[3];
  408. tmp2[2] = tmp1[0];
  409. tmp2[3] = tmp1[1];
  410. memcpy(&data[i], tmp2, 4);
  411. break;
  412. default:
  413. break;
  414. }
  415. }
  416. return true;
  417. }
  418. else
  419. return false;
  420. }
  421. // ##################################################################################################
  422. bool mmodbus_readHoldingRegister32i(uint8_t slaveAddress, uint16_t number, uint32_t *data)
  423. {
  424. return mmodbus_readHoldingRegisters32i(slaveAddress, number, 1, data);
  425. }
  426. // ##################################################################################################
  427. bool mmodbus_readHoldingRegisters32i(uint8_t slaveAddress, uint16_t startnumber, uint16_t length, uint32_t *data)
  428. {
  429. return mmodbus_readHoldingRegisters32f(slaveAddress, startnumber, length, (float *)data);
  430. }
  431. // ##################################################################################################
  432. bool mmodbus_readHoldingRegister16i(uint8_t slaveAddress, uint16_t number, uint16_t *data)
  433. {
  434. return mmodbus_readHoldingRegisters16i(slaveAddress, number, 1, data);
  435. }
  436. // ##################################################################################################
  437. bool mmodbus_readHoldingRegisters16i(uint8_t slaveAddress, uint16_t startnumber, uint16_t length, uint16_t *data)
  438. {
  439. bool ret = mmodbus_readHoldingRegisters8i(slaveAddress, startnumber, length * 1, (uint8_t *)data);
  440. if (ret == true)
  441. {
  442. uint8_t tmp1[2], tmp2[2];
  443. for (uint16_t i = 0; i < length; i++)
  444. {
  445. switch (mmodbus.byteOrder16)
  446. {
  447. case MModBus_16bitOrder_AB:
  448. memcpy(tmp1, &data[i], 2);
  449. tmp2[0] = tmp1[0];
  450. tmp2[1] = tmp1[1];
  451. memcpy(&data[i], tmp2, 2);
  452. break;
  453. default:
  454. memcpy(tmp1, &data[i], 2);
  455. tmp2[0] = tmp1[1];
  456. tmp2[1] = tmp1[0];
  457. memcpy(&data[i], tmp2, 2);
  458. break;
  459. }
  460. }
  461. return true;
  462. }
  463. else
  464. return false;
  465. }
  466. // ##################################################################################################
  467. bool mmodbus_writeCoil(uint8_t slaveAddress, uint16_t number, uint8_t data)
  468. {
  469. #if (_MMODBUS_RTU == 1)
  470. uint8_t txData[8];
  471. txData[0] = slaveAddress;
  472. txData[1] = MModbusCMD_WriteSingleCoil;
  473. txData[2] = (number & 0xFF00) >> 8;
  474. txData[3] = (number & 0x00FF);
  475. if (data == 0)
  476. txData[4] = 0;
  477. else
  478. txData[4] = 0xFF;
  479. txData[5] = 0;
  480. static uint16_t crc;
  481. crc = mmodbus_crc16(txData, 6);
  482. txData[6] = (crc & 0x00FF);
  483. txData[7] = (crc & 0xFF00) >> 8;
  484. mmodbus_sendRaw(txData, 8, 100);
  485. uint16_t recLen = mmodbus_receiveRaw(mmodbus.timeout);
  486. if (recLen == 0)
  487. return false;
  488. if (memcmp(txData, mmodbus.rxBuf, 8) == 0)
  489. return true;
  490. else
  491. return false;
  492. #endif
  493. #if (_MMODBUS_ASCII == 1)
  494. #endif
  495. }
  496. // ##################################################################################################
  497. bool mmodbus_writeHoldingRegister16i(uint8_t slaveAddress, uint16_t number, uint16_t data)
  498. {
  499. #if (_MMODBUS_RTU == 1)
  500. uint8_t txData[8];
  501. txData[0] = slaveAddress;
  502. txData[1] = MModbusCMD_WriteSingleRegister;
  503. txData[2] = (number & 0xFF00) >> 8;
  504. txData[3] = (number & 0x00FF);
  505. txData[4] = (data & 0xFF00) >> 8;
  506. txData[5] = data & 0x00FF;
  507. static uint16_t crc;
  508. crc = mmodbus_crc16(txData, 6);
  509. txData[6] = (crc & 0x00FF);
  510. txData[7] = (crc & 0xFF00) >> 8;
  511. mmodbus_sendRaw(txData, 8, 100);
  512. uint16_t recLen = mmodbus_receiveRaw(mmodbus.timeout);
  513. if (recLen == 0)
  514. return false;
  515. if (memcmp(txData, mmodbus.rxBuf, 8) == 0)
  516. return true;
  517. else
  518. return false;
  519. #endif
  520. #if (_MMODBUS_ASCII == 1)
  521. #endif
  522. }
  523. // ##################################################################################################
  524. bool mmodbus_writeHoldingRegisters16i(uint8_t slaveAddress, uint16_t startnumber, uint16_t length, uint16_t *data)
  525. {
  526. #if (_MMODBUS_RTU == 1)
  527. if (length == 1)
  528. {
  529. return mmodbus_writeHoldingRegister16i(slaveAddress, startnumber, data[0]);
  530. }
  531. else
  532. {
  533. uint8_t txData[7 + length * 2 + 2];
  534. txData[0] = slaveAddress;
  535. txData[1] = MModbusCMD_WriteMultipleRegisters;
  536. txData[2] = (startnumber & 0xFF00) >> 8;
  537. txData[3] = (startnumber & 0x00FF);
  538. txData[4] = (length & 0xFF00) >> 8;
  539. txData[5] = (length & 0x00FF);
  540. txData[6] = (length * 2);
  541. uint8_t tmp1[2], tmp2[2];
  542. for (uint16_t i = 0; i < length; i++)
  543. {
  544. switch (mmodbus.byteOrder16)
  545. {
  546. case MModBus_16bitOrder_AB:
  547. memcpy(tmp1, &data[i], 2);
  548. tmp2[0] = tmp1[1];
  549. tmp2[1] = tmp1[0];
  550. memcpy(&txData[7 + i * 2], tmp2, 2);
  551. break;
  552. default:
  553. memcpy(tmp1, &data[i], 2);
  554. tmp2[0] = tmp1[0];
  555. tmp2[1] = tmp1[1];
  556. memcpy(&txData[7 + i * 2], tmp2, 2);
  557. break;
  558. }
  559. }
  560. static uint16_t crc;
  561. crc = mmodbus_crc16(txData, 7 + length * 2);
  562. txData[7 + length * 2 + 0] = (crc & 0x00FF);
  563. txData[7 + length * 2 + 1] = (crc & 0xFF00) >> 8;
  564. mmodbus_sendRaw(txData, 7 + length * 2 + 2, 100);
  565. uint16_t recLen = mmodbus_receiveRaw(mmodbus.timeout);
  566. if (recLen == 0)
  567. return false;
  568. crc = mmodbus_crc16(txData, 6);
  569. txData[6] = (crc & 0x00FF);
  570. txData[7] = (crc & 0xFF00) >> 8;
  571. if (memcmp(txData, mmodbus.rxBuf, 8) == 0)
  572. return true;
  573. else
  574. return false;
  575. }
  576. #endif
  577. #if (_MMODBUS_ASCII == 1)
  578. #endif
  579. }
  580. // ##################################################################################################