mmodbus.c 20 KB

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