modbus_rtu.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. #include "modbus_rtu.h"
  2. #include "FreeRTOS.h"
  3. #include "crcLib.h"
  4. #include "task.h"
  5. #include <string.h>
  6. static modbus_rtu_trans_fun trans_fun;
  7. static modbus_rtu_recive_fun recive_fun;
  8. void modbus_rtu_on_data_cb(uint8_t *data, uint16_t len);
  9. void modbus_rtu_master_on_data_cb(uint8_t *data, uint16_t len);
  10. void modbus_rtu_slave_on_data_cb(uint8_t *data, uint16_t len);
  11. void modbus_rtu_task(void *arg)
  12. {
  13. uint8_t *data = NULL;
  14. uint16_t len = 0;
  15. uint8_t res = 0;
  16. while (1)
  17. {
  18. data = recive_fun(10, &len);
  19. if (data != NULL)
  20. {
  21. modbus_rtu_on_data_cb(data, len);
  22. }
  23. vTaskDelay(pdMS_TO_TICKS(2));
  24. }
  25. }
  26. void modbus_rtu_init(modbus_rtu_trans_fun trans, modbus_rtu_recive_fun recive)
  27. {
  28. trans_fun = trans;
  29. recive_fun = recive;
  30. xTaskCreate(modbus_rtu_task, "mb_rtu", 150, NULL, 2, NULL);
  31. }
  32. void modbus_rtu_on_data_cb(uint8_t *data, uint16_t len)
  33. {
  34. if (modbus_get_mode() == 0)
  35. {
  36. // modbus_rtu_master_on_data_cb(data, len);
  37. }
  38. else
  39. {
  40. modbus_rtu_slave_on_data_cb(data, len);
  41. }
  42. }
  43. void modbus_rtu_slave_on_data_cb(uint8_t *data, uint16_t len)
  44. {
  45. modbus_slave_t *modbus_slave = modbus_slave_get();
  46. if (len < 5)
  47. {
  48. return;
  49. }
  50. uint16_t crc = crc16_modbus(data, len - 2);
  51. uint16_t bcrc = (data[len - 1] << 8) + data[len - 2];
  52. if (crc != bcrc)
  53. {
  54. return;
  55. }
  56. uint8_t address = data[0];
  57. uint8_t function = data[1];
  58. if (address != modbus_slave->address)
  59. {
  60. return;
  61. }
  62. modbus_slave->send_buffer_len = 0;
  63. modbus_slave->send_buffer[modbus_slave->send_buffer_len++] = address;
  64. modbus_slave->send_buffer[modbus_slave->send_buffer_len++] = function;
  65. switch (function)
  66. {
  67. case 0x03:
  68. {
  69. if (len != 8)
  70. {
  71. modbus_slave->send_buffer[1] |= 0x80;
  72. modbus_slave->send_buffer[2] = 0x01;
  73. modbus_slave->send_buffer_len += 2;
  74. break;
  75. }
  76. uint16_t reg_addr = (data[2] << 8) + data[3];
  77. uint16_t reg_num = (data[4] << 8) + data[5];
  78. uint16_t *tmp = pvPortMalloc(sizeof(uint16_t) * reg_num);
  79. int8_t res = modbus_slave_reg_read_mult(reg_addr, reg_num, tmp);
  80. if (res != 0)
  81. {
  82. modbus_slave->send_buffer[1] |= 0x80;
  83. modbus_slave->send_buffer[2] = 0x02;
  84. modbus_slave->send_buffer_len += 2;
  85. vPortFree(tmp);
  86. break;
  87. }
  88. for (uint16_t i = 0; i < reg_num; i++)
  89. {
  90. modbus_slave->send_buffer[3 + i * 2] = tmp[i] >> 8;
  91. modbus_slave->send_buffer[4 + i * 2] = tmp[i] & 0xFF;
  92. }
  93. vPortFree(tmp);
  94. modbus_slave->send_buffer[2] = reg_num * 2;
  95. modbus_slave->send_buffer_len += reg_num * 2 + 1;
  96. break;
  97. }
  98. case 0x06:
  99. {
  100. if (len != 8)
  101. {
  102. modbus_slave->send_buffer[1] |= 0x80;
  103. modbus_slave->send_buffer[2] = 0x01;
  104. modbus_slave->send_buffer_len += 2;
  105. break;
  106. }
  107. uint16_t reg_addr = (data[2] << 8) + data[3];
  108. uint16_t reg_data = (data[4] << 8) + data[5];
  109. int8_t res = modbus_slave_reg_write(reg_addr, reg_data);
  110. if (res != 0)
  111. {
  112. modbus_slave->send_buffer[1] |= 0x80;
  113. modbus_slave->send_buffer[2] = 0x02;
  114. modbus_slave->send_buffer_len += 2;
  115. break;
  116. }
  117. modbus_slave->send_buffer[2] = reg_addr >> 8;
  118. modbus_slave->send_buffer[3] = reg_addr & 0xFF;
  119. modbus_slave->send_buffer[4] = reg_data >> 8;
  120. modbus_slave->send_buffer[5] = reg_data & 0xFF;
  121. modbus_slave->send_buffer_len += 4;
  122. break;
  123. }
  124. case 0x10:
  125. {
  126. if (len != 9 + data[6])
  127. {
  128. modbus_slave->send_buffer[1] |= 0x80;
  129. modbus_slave->send_buffer[2] = 0x01;
  130. modbus_slave->send_buffer_len += 2;
  131. break;
  132. }
  133. uint16_t reg_addr = (data[2] << 8) + data[3];
  134. uint16_t reg_num = (data[4] << 8) + data[5];
  135. uint16_t *tmp = pvPortMalloc(sizeof(uint16_t) * reg_num);
  136. for (uint8_t i = 0; i < reg_num; i++)
  137. {
  138. tmp[i] = (data[7 + i * 2] << 8) + data[8 + i * 2];
  139. }
  140. int8_t res = modbus_slave_reg_write_mult(reg_addr, reg_num, tmp);
  141. vPortFree(tmp);
  142. if (res != 0)
  143. {
  144. modbus_slave->send_buffer[1] |= 0x80;
  145. modbus_slave->send_buffer[2] = 0x02;
  146. modbus_slave->send_buffer_len += 2;
  147. break;
  148. }
  149. modbus_slave->send_buffer[2] = reg_addr >> 8;
  150. modbus_slave->send_buffer[3] = reg_addr & 0xFF;
  151. modbus_slave->send_buffer[4] = reg_num >> 8;
  152. modbus_slave->send_buffer[5] = reg_num & 0xFF;
  153. modbus_slave->send_buffer_len += 4;
  154. break;
  155. }
  156. case 0x64 ... 0x6e:
  157. {
  158. if (len != 5 + data[2])
  159. {
  160. modbus_slave->send_buffer[1] |= 0x80;
  161. modbus_slave->send_buffer[2] = 0x01;
  162. modbus_slave->send_buffer_len += 2;
  163. break;
  164. }
  165. uint8_t cmd = data[1];
  166. modbus_cmd_t *box = modbus_slave_cmd_get(cmd);
  167. if (box == NULL)
  168. {
  169. modbus_slave->send_buffer[1] |= 0x80;
  170. modbus_slave->send_buffer[2] = 0x01;
  171. modbus_slave->send_buffer_len += 2;
  172. break;
  173. }
  174. uint8_t res_len = 0;
  175. box->cb(data + 3, data[2], modbus_slave->send_buffer + 3, &res_len);
  176. modbus_slave->send_buffer[2] = res_len;
  177. modbus_slave->send_buffer_len += res_len +1;
  178. break;
  179. }
  180. default:
  181. modbus_slave->send_buffer[1] |= 0x80;
  182. modbus_slave->send_buffer[2] = 0x01;
  183. modbus_slave->send_buffer_len += 2;
  184. break;
  185. }
  186. crc = crc16_modbus(modbus_slave->send_buffer, modbus_slave->send_buffer_len);
  187. modbus_slave->send_buffer[modbus_slave->send_buffer_len++] = crc & 0xFF;
  188. modbus_slave->send_buffer[modbus_slave->send_buffer_len++] = crc >> 8;
  189. trans_fun(modbus_slave->send_buffer, modbus_slave->send_buffer_len);
  190. }
  191. void modbus_rtu_cmd_echo(uint8_t* data,uint8_t len,uint8_t* outData,uint8_t* outLen)
  192. {
  193. memcpy(outData,data,len);
  194. *outLen = len;
  195. }