agile_modbus.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. /**
  2. * @file agile_modbus.h
  3. * @brief Agile Modbus software package common header file
  4. * @author Ma Longwei (2544047213@qq.com)
  5. * @date 2022-07-28
  6. *
  7. * @attention
  8. *
  9. * <h2><center>&copy; Copyright (c) 2021 Ma Longwei.
  10. * All rights reserved.</center></h2>
  11. *
  12. */
  13. #ifndef __PKG_AGILE_MODBUS_H
  14. #define __PKG_AGILE_MODBUS_H
  15. #ifdef __cplusplus
  16. extern "C" {
  17. #endif
  18. #include <stdint.h>
  19. /** @addtogroup COMMON
  20. * @{
  21. */
  22. /** @defgroup Modbus_Module_Definition Modbus Module Definition
  23. * @{
  24. */
  25. #ifndef AGILE_MODBUS_USING_RTU
  26. #define AGILE_MODBUS_USING_RTU 1
  27. #endif /* AGILE_MODBUS_USING_RTU */
  28. #ifndef AGILE_MODBUS_USING_TCP
  29. #define AGILE_MODBUS_USING_TCP 1
  30. #endif /* AGILE_MODBUS_USING_TCP */
  31. /**
  32. * @}
  33. */
  34. /** @defgroup COMMON_Exported_Constants Common Exported Constants
  35. * @{
  36. */
  37. /** @defgroup Modbus_Function_Codes Modbus Function Codes
  38. * @{
  39. */
  40. #define AGILE_MODBUS_FC_READ_COILS 0x01
  41. #define AGILE_MODBUS_FC_READ_DISCRETE_INPUTS 0x02
  42. #define AGILE_MODBUS_FC_READ_HOLDING_REGISTERS 0x03
  43. #define AGILE_MODBUS_FC_READ_INPUT_REGISTERS 0x04
  44. #define AGILE_MODBUS_FC_WRITE_SINGLE_COIL 0x05
  45. #define AGILE_MODBUS_FC_WRITE_SINGLE_REGISTER 0x06
  46. #define AGILE_MODBUS_FC_READ_EXCEPTION_STATUS 0x07
  47. #define AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS 0x0F
  48. #define AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10
  49. #define AGILE_MODBUS_FC_REPORT_SLAVE_ID 0x11
  50. #define AGILE_MODBUS_FC_MASK_WRITE_REGISTER 0x16
  51. #define AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS 0x17
  52. /**
  53. * @}
  54. */
  55. /** @defgroup Modbus_Constants Modbus Constants
  56. * @{
  57. */
  58. #define AGILE_MODBUS_VERSION_STRING "AMB_1.1.4" /**< Agile Modbus version number */
  59. #define AGILE_MODBUS_BROADCAST_ADDRESS 0 /**< Modbus broadcast address */
  60. /** @name Quantity limit of Coils
  61. @verbatim
  62. Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 1 page 12)
  63. Quantity of Coils to read (2 bytes): 1 to 2000 (0x7D0)
  64. (chapter 6 section 11 page 29)
  65. Quantity of Coils to write (2 bytes): 1 to 1968 (0x7B0)
  66. @endverbatim
  67. * @{
  68. */
  69. #define AGILE_MODBUS_MAX_READ_BITS 2000
  70. #define AGILE_MODBUS_MAX_WRITE_BITS 1968
  71. /**
  72. * @}
  73. */
  74. /** @name Quantity limit of Registers
  75. @verbatim
  76. Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 3 page 15)
  77. Quantity of Registers to read (2 bytes): 1 to 125 (0x7D)
  78. (chapter 6 section 12 page 31)
  79. Quantity of Registers to write (2 bytes) 1 to 123 (0x7B)
  80. (chapter 6 section 17 page 38)
  81. Quantity of Registers to write in R/W registers (2 bytes) 1 to 121 (0x79)
  82. @endverbatim
  83. * @{
  84. */
  85. #define AGILE_MODBUS_MAX_READ_REGISTERS 125
  86. #define AGILE_MODBUS_MAX_WRITE_REGISTERS 123
  87. #define AGILE_MODBUS_MAX_WR_WRITE_REGISTERS 121
  88. #define AGILE_MODBUS_MAX_WR_READ_REGISTERS 125
  89. /**
  90. * @}
  91. */
  92. /**
  93. @verbatim
  94. The size of the MODBUS PDU is limited by the size constraint inherited from
  95. the first MODBUS implementation on Serial Line network (max. RS485 ADU = 256
  96. bytes). Therefore, MODBUS PDU for serial line communication = 256 - Server
  97. address (1 byte) - CRC (2 bytes) = 253 bytes.
  98. @endverbatim
  99. */
  100. #define AGILE_MODBUS_MAX_PDU_LENGTH 253
  101. /**
  102. @verbatim
  103. Consequently:
  104. - RTU MODBUS ADU = 253 bytes + Server address (1 byte) + CRC (2 bytes) = 256
  105. bytes.
  106. - TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes.
  107. so the maximum of both backend in 260 bytes. This size can used to allocate
  108. an array of bytes to store responses and it will be compatible with the two
  109. backends.
  110. @endverbatim
  111. */
  112. #define AGILE_MODBUS_MAX_ADU_LENGTH 260
  113. /**
  114. * @}
  115. */
  116. /**
  117. * @}
  118. */
  119. /** @defgroup COMMON_Exported_Types Common Exported Types
  120. * @{
  121. */
  122. /**
  123. * @brief Modbus exception code
  124. */
  125. enum {
  126. AGILE_MODBUS_EXCEPTION_ILLEGAL_FUNCTION = 0x01,
  127. AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,
  128. AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
  129. AGILE_MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE,
  130. AGILE_MODBUS_EXCEPTION_ACKNOWLEDGE,
  131. AGILE_MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY,
  132. AGILE_MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE,
  133. AGILE_MODBUS_EXCEPTION_MEMORY_PARITY,
  134. AGILE_MODBUS_EXCEPTION_NOT_DEFINED,
  135. AGILE_MODBUS_EXCEPTION_GATEWAY_PATH,
  136. AGILE_MODBUS_EXCEPTION_GATEWAY_TARGET,
  137. AGILE_MODBUS_EXCEPTION_UNKNOW = 0xff
  138. };
  139. /**
  140. *@ brief Modbus backend type
  141. */
  142. typedef enum {
  143. AGILE_MODBUS_BACKEND_TYPE_RTU = 0, /**< RTU */
  144. AGILE_MODBUS_BACKEND_TYPE_TCP /**< TCP */
  145. } agile_modbus_backend_type_t;
  146. /**
  147. * @brief Modbus received message type
  148. *
  149. @verbatim
  150. ---------- Request Indication ----------
  151. | Client | ---------------------->| Server |
  152. ---------- Confirmation Response ----------
  153. @endverbatim
  154. */
  155. typedef enum {
  156. AGILE_MODBUS_MSG_INDICATION, /**< Host-side request message */
  157. AGILE_MODBUS_MSG_CONFIRMATION /**< Server-side request message */
  158. } agile_modbus_msg_type_t;
  159. /**
  160. * @brief contains the modbus header parameter structure
  161. */
  162. typedef struct agile_modbus_sft {
  163. int slave; /**< slave address */
  164. int function; /**< function code */
  165. int t_id; /**< Transaction identifier */
  166. } agile_modbus_sft_t;
  167. typedef struct agile_modbus agile_modbus_t; /**< Agile Modbus structure */
  168. /**
  169. * @brief Agile Modbus backend interface structure
  170. */
  171. typedef struct agile_modbus_backend {
  172. uint32_t backend_type; /**< Backend type */
  173. uint32_t header_length; /**<Header length, excluding function code */
  174. uint32_t checksum_length; /**< Check data length */
  175. uint32_t max_adu_length; /**< Backend ADU length */
  176. int (*set_slave)(agile_modbus_t *ctx, int slave); /**< Set address interface */
  177. int (*build_request_basis)(agile_modbus_t *ctx, int function, int addr,
  178. int nb, uint8_t *req); /**< Build a basic request message interface */
  179. int (*build_response_basis)(agile_modbus_sft_t *sft, uint8_t *rsp); /**< Build a basic response message interface */
  180. int (*prepare_response_tid)(const uint8_t *req, int *req_length); /**< Prepare response interface */
  181. int (*send_msg_pre)(uint8_t *req, int req_length); /**< Pre-send data interface */
  182. int (*check_integrity)(agile_modbus_t *ctx, uint8_t *msg, const int msg_length); /**< Check the receive data integrity interface */
  183. int (*pre_check_confirmation)(agile_modbus_t *ctx, const uint8_t *req,
  184. const uint8_t *rsp, int rsp_length); /**< Pre-check confirmation interface */
  185. } agile_modbus_backend_t;
  186. /**
  187. * @brief Agile Modbus structure
  188. */
  189. struct agile_modbus {
  190. int slave; /**< slave address */
  191. uint8_t *send_buf; /**< Send buffer */
  192. int send_bufsz; /**<Send buffer size */
  193. uint8_t *read_buf; /**<Receive buffer */
  194. int read_bufsz; /**<Receive buffer size */
  195. uint8_t (*compute_meta_length_after_function)(agile_modbus_t *ctx, int function,
  196. agile_modbus_msg_type_t msg_type); /**< Customized calculation data element length interface */
  197. int (*compute_data_length_after_meta)(agile_modbus_t *ctx, uint8_t *msg,
  198. int msg_length, agile_modbus_msg_type_t msg_type); /**< Customized calculation data length interface */
  199. const agile_modbus_backend_t *backend; /**< Backend interface */
  200. void *backend_data; /**< Backend data, pointing to RTU or TCP structure */
  201. };
  202. /**
  203. * @}
  204. */
  205. /** @addtogroup Modbus_Slave
  206. * @{
  207. */
  208. /** @defgroup Slave_Exported_Types Slave Exported Types
  209. * @{
  210. */
  211. /**
  212. * @brief Agile Modbus slave information structure
  213. */
  214. struct agile_modbus_slave_info {
  215. agile_modbus_sft_t *sft; /**< sft structure pointer */
  216. int *rsp_length; /**<Response data length pointer */
  217. int address; /**< Register address */
  218. int nb; /**< number */
  219. uint8_t *buf; /**< Data fields required for different function codes */
  220. int send_index; /**< Current index of sending buffer */
  221. };
  222. /**
  223. * @brief Slave callback function
  224. * @param ctx modbus handle
  225. * @param slave_info slave information body
  226. * @param data private data
  227. * @return =0: normal;
  228. * <0: Abnormal
  229. * (-AGILE_MODBUS_EXCEPTION_UNKNOW(-255): Unknown exception, the slave will not package the response data)
  230. * (Other negative exception codes: package exception response data from the opportunity)
  231. */
  232. typedef int (*agile_modbus_slave_callback_t)(agile_modbus_t *ctx, struct agile_modbus_slave_info *slave_info, const void *data);
  233. /**
  234. * @}
  235. */
  236. /**
  237. * @}
  238. */
  239. /** @addtogroup COMMON_Exported_Functions
  240. * @{
  241. */
  242. void agile_modbus_common_init(agile_modbus_t *ctx, uint8_t *send_buf, int send_bufsz, uint8_t *read_buf, int read_bufsz);
  243. int agile_modbus_set_slave(agile_modbus_t *ctx, int slave);
  244. void agile_modbus_set_compute_meta_length_after_function_cb(agile_modbus_t *ctx,
  245. uint8_t (*cb)(agile_modbus_t *ctx, int function,
  246. agile_modbus_msg_type_t msg_type));
  247. void agile_modbus_set_compute_data_length_after_meta_cb(agile_modbus_t *ctx,
  248. int (*cb)(agile_modbus_t *ctx, uint8_t *msg,
  249. int msg_length, agile_modbus_msg_type_t msg_type));
  250. int agile_modbus_receive_judge(agile_modbus_t *ctx, int msg_length, agile_modbus_msg_type_t msg_type);
  251. /**
  252. * @}
  253. */
  254. /** @addtogroup Modbus_Master
  255. * @{
  256. */
  257. /** @addtogroup Master_Common_Operation_Functions
  258. * @{
  259. */
  260. int agile_modbus_serialize_read_bits(agile_modbus_t *ctx, int addr, int nb);
  261. int agile_modbus_deserialize_read_bits(agile_modbus_t *ctx, int msg_length, uint8_t *dest);
  262. int agile_modbus_serialize_read_input_bits(agile_modbus_t *ctx, int addr, int nb);
  263. int agile_modbus_deserialize_read_input_bits(agile_modbus_t *ctx, int msg_length, uint8_t *dest);
  264. int agile_modbus_serialize_read_registers(agile_modbus_t *ctx, int addr, int nb);
  265. int agile_modbus_deserialize_read_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest);
  266. int agile_modbus_serialize_read_input_registers(agile_modbus_t *ctx, int addr, int nb);
  267. int agile_modbus_deserialize_read_input_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest);
  268. int agile_modbus_serialize_write_bit(agile_modbus_t *ctx, int addr, int status);
  269. int agile_modbus_deserialize_write_bit(agile_modbus_t *ctx, int msg_length);
  270. int agile_modbus_serialize_write_register(agile_modbus_t *ctx, int addr, const uint16_t value);
  271. int agile_modbus_deserialize_write_register(agile_modbus_t *ctx, int msg_length);
  272. int agile_modbus_serialize_write_bits(agile_modbus_t *ctx, int addr, int nb, const uint8_t *src);
  273. int agile_modbus_deserialize_write_bits(agile_modbus_t *ctx, int msg_length);
  274. int agile_modbus_serialize_write_registers(agile_modbus_t *ctx, int addr, int nb, const uint16_t *src);
  275. int agile_modbus_deserialize_write_registers(agile_modbus_t *ctx, int msg_length);
  276. int agile_modbus_serialize_mask_write_register(agile_modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask);
  277. int agile_modbus_deserialize_mask_write_register(agile_modbus_t *ctx, int msg_length);
  278. int agile_modbus_serialize_write_and_read_registers(agile_modbus_t *ctx,
  279. int write_addr, int write_nb,
  280. const uint16_t *src,
  281. int read_addr, int read_nb);
  282. int agile_modbus_deserialize_write_and_read_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest);
  283. int agile_modbus_serialize_report_slave_id(agile_modbus_t *ctx);
  284. int agile_modbus_deserialize_report_slave_id(agile_modbus_t *ctx, int msg_length, int max_dest, uint8_t *dest);
  285. /**
  286. * @}
  287. */
  288. /** @addtogroup Master_Raw_Operation_Functions
  289. * @{
  290. */
  291. int agile_modbus_compute_response_length_from_request(agile_modbus_t *ctx, uint8_t *req);
  292. int agile_modbus_serialize_raw_request(agile_modbus_t *ctx, const uint8_t *raw_req, int raw_req_length);
  293. int agile_modbus_deserialize_raw_response(agile_modbus_t *ctx, int msg_length);
  294. /**
  295. * @}
  296. */
  297. /**
  298. * @}
  299. */
  300. /** @addtogroup Modbus_Slave
  301. * @{
  302. */
  303. /** @addtogroup Slave_Operation_Functions
  304. * @{
  305. */
  306. int agile_modbus_slave_handle(agile_modbus_t *ctx, int msg_length, uint8_t slave_strict,
  307. agile_modbus_slave_callback_t slave_cb, const void *slave_data, int *frame_length);
  308. void agile_modbus_slave_io_set(uint8_t *buf, int index, int status);
  309. uint8_t agile_modbus_slave_io_get(uint8_t *buf, int index);
  310. void agile_modbus_slave_register_set(uint8_t *buf, int index, uint16_t data);
  311. uint16_t agile_modbus_slave_register_get(uint8_t *buf, int index);
  312. /**
  313. * @}
  314. */
  315. /**
  316. * @}
  317. */
  318. /**
  319. * @}
  320. */
  321. /* Include RTU and TCP module */
  322. #if AGILE_MODBUS_USING_RTU
  323. #include "agile_modbus_rtu.h"
  324. #endif /* AGILE_MODBUS_USING_RTU */
  325. #if AGILE_MODBUS_USING_TCP
  326. #include "agile_modbus_tcp.h"
  327. #endif /* AGILE_MODBUS_USING_TCP */
  328. #ifdef __cplusplus
  329. }
  330. #endif
  331. #endif /* __PKG_AGILE_MODBUS_H */