nanoMODBUS
nanomodbus.h
Go to the documentation of this file.
1 /*
2  nanoMODBUS - A compact MODBUS RTU/TCP C library for microcontrollers
3 
4  MIT License
5 
6  Copyright (c) 2022 Valerio De Benedetto (@debevv)
7 
8  Permission is hereby granted, free of charge, to any person obtaining a copy
9  of this software and associated documentation files (the "Software"), to deal
10  in the Software without restriction, including without limitation the rights
11  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  copies of the Software, and to permit persons to whom the Software is
13  furnished to do so, subject to the following conditions:
14 
15  The above copyright notice and this permission notice shall be included in all
16  copies or substantial portions of the Software.
17 
18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  SOFTWARE.
25 */
26 
27 
40 #ifndef NANOMODBUS_H
41 #define NANOMODBUS_H
42 
43 #include <stdbool.h>
44 #include <stdint.h>
45 #include <string.h>
46 
47 #ifdef __cplusplus
48 extern "C" {
49 #endif
50 
55 typedef enum nmbs_error {
56  // Library errors
67  // Modbus exceptions
73 
74 
79 #define nmbs_error_is_exception(e) ((e) > 0 && (e) < 5)
80 
81 
85 typedef uint8_t nmbs_bitfield[250];
86 
90 typedef uint8_t nmbs_bitfield_256[32];
91 
95 #define nmbs_bitfield_read(bf, b) ((bool) ((bf)[(b) / 8] & (0x1 << ((b) % 8))))
96 
100 #define nmbs_bitfield_set(bf, b) (((bf)[(b) / 8]) = (((bf)[(b) / 8]) | (0x1 << ((b) % 8))))
101 
105 #define nmbs_bitfield_unset(bf, b) (((bf)[(b) / 8]) = (((bf)[(b) / 8]) & ~(0x1 << ((b) % 8))))
106 
110 #define nmbs_bitfield_write(bf, b, v) \
111  (((bf)[(b) / 8]) = ((v) ? (((bf)[(b) / 8]) | (0x1 << ((b) % 8))) : (((bf)[(b) / 8]) & ~(0x1 << ((b) % 8)))))
112 
116 #define nmbs_bitfield_reset(bf) memset(bf, 0, sizeof(bf))
117 
121 typedef enum nmbs_transport {
122  NMBS_TRANSPORT_RTU = 1,
123  NMBS_TRANSPORT_TCP = 2,
125 
126 
146 typedef struct nmbs_platform_conf {
148  int32_t (*read)(uint8_t* buf, uint16_t count, int32_t byte_timeout_ms,
149  void* arg);
150  int32_t (*write)(const uint8_t* buf, uint16_t count, int32_t byte_timeout_ms,
151  void* arg);
152  void* arg;
154 
155 
164 typedef struct nmbs_callbacks {
165 #ifndef NMBS_SERVER_DISABLED
166 #ifndef NMBS_SERVER_READ_COILS_DISABLED
167  nmbs_error (*read_coils)(uint16_t address, uint16_t quantity, nmbs_bitfield coils_out, uint8_t unit_id, void* arg);
168 #endif
169 
170 #ifndef NMBS_SERVER_READ_DISCRETE_INPUTS_DISABLED
171  nmbs_error (*read_discrete_inputs)(uint16_t address, uint16_t quantity, nmbs_bitfield inputs_out, uint8_t unit_id,
172  void* arg);
173 #endif
174 
175 #ifndef NMBS_SERVER_READ_HOLDING_REGISTERS_DISABLED
176  nmbs_error (*read_holding_registers)(uint16_t address, uint16_t quantity, uint16_t* registers_out, uint8_t unit_id,
177  void* arg);
178 #endif
179 
180 #ifndef NMBS_SERVER_READ_INPUT_REGISTERS_DISABLED
181  nmbs_error (*read_input_registers)(uint16_t address, uint16_t quantity, uint16_t* registers_out, uint8_t unit_id,
182  void* arg);
183 #endif
184 
185 #ifndef NMBS_SERVER_WRITE_SINGLE_COIL_DISABLED
186  nmbs_error (*write_single_coil)(uint16_t address, bool value, uint8_t unit_id, void* arg);
187 #endif
188 
189 #ifndef NMBS_SERVER_WRITE_SINGLE_REGISTER_DISABLED
190  nmbs_error (*write_single_register)(uint16_t address, uint16_t value, uint8_t unit_id, void* arg);
191 #endif
192 
193 #ifndef NMBS_SERVER_WRITE_MULTIPLE_COILS_DISABLED
194  nmbs_error (*write_multiple_coils)(uint16_t address, uint16_t quantity, const nmbs_bitfield coils, uint8_t unit_id,
195  void* arg);
196 #endif
197 
198 #ifndef NMBS_SERVER_WRITE_MULTIPLE_REGISTERS_DISABLED
199  nmbs_error (*write_multiple_registers)(uint16_t address, uint16_t quantity, const uint16_t* registers,
200  uint8_t unit_id, void* arg);
201 #endif
202 
203 #ifndef NMBS_SERVER_READ_FILE_RECORD_DISABLED
204  nmbs_error (*read_file_record)(uint16_t file_number, uint16_t record_number, uint16_t* registers, uint16_t count,
205  uint8_t unit_id, void* arg);
206 #endif
207 
208 #ifndef NMBS_SERVER_WRITE_FILE_RECORD_DISABLED
209  nmbs_error (*write_file_record)(uint16_t file_number, uint16_t record_number, const uint16_t* registers,
210  uint16_t count, uint8_t unit_id, void* arg);
211 #endif
212 
213 #ifndef NMBS_SERVER_READ_DEVICE_IDENTIFICATION_DISABLED
214 #define NMBS_DEVICE_IDENTIFICATION_STRING_LENGTH 128
215  nmbs_error (*read_device_identification)(uint8_t object_id, char buffer[NMBS_DEVICE_IDENTIFICATION_STRING_LENGTH]);
216  nmbs_error (*read_device_identification_map)(nmbs_bitfield_256 map);
217 #endif
218 #endif
219 
220  void* arg; // User data, will be passed to functions above
222 
223 
228 typedef struct nmbs_t {
229  struct {
230  uint8_t buf[260];
231  uint16_t buf_idx;
232 
233  uint8_t unit_id;
234  uint8_t fc;
235  uint16_t transaction_id;
236  bool broadcast;
237  bool ignored;
238  } msg;
239 
240  nmbs_callbacks callbacks;
241 
242  int32_t byte_timeout_ms;
243  int32_t read_timeout_ms;
244 
245  nmbs_platform_conf platform;
246 
247  uint8_t address_rtu;
248  uint8_t dest_address_rtu;
249  uint16_t current_tid;
251 
255 static const uint8_t NMBS_BROADCAST_ADDRESS = 0;
256 
264 void nmbs_set_read_timeout(nmbs_t* nmbs, int32_t timeout_ms);
265 
270 void nmbs_set_byte_timeout(nmbs_t* nmbs, int32_t timeout_ms);
271 
276 void nmbs_set_platform_arg(nmbs_t* nmbs, void* arg);
277 
278 #ifndef NMBS_SERVER_DISABLED
287 nmbs_error nmbs_server_create(nmbs_t* nmbs, uint8_t address_rtu, const nmbs_platform_conf* platform_conf,
288  const nmbs_callbacks* callbacks);
289 
298 
303 void nmbs_set_callbacks_arg(nmbs_t* nmbs, void* arg);
304 #endif
305 
306 #ifndef NMBS_CLIENT_DISABLED
313 nmbs_error nmbs_client_create(nmbs_t* nmbs, const nmbs_platform_conf* platform_conf);
314 
319 void nmbs_set_destination_rtu_address(nmbs_t* nmbs, uint8_t address);
320 
329 nmbs_error nmbs_read_coils(nmbs_t* nmbs, uint16_t address, uint16_t quantity, nmbs_bitfield coils_out);
330 
339 nmbs_error nmbs_read_discrete_inputs(nmbs_t* nmbs, uint16_t address, uint16_t quantity, nmbs_bitfield inputs_out);
340 
349 nmbs_error nmbs_read_holding_registers(nmbs_t* nmbs, uint16_t address, uint16_t quantity, uint16_t* registers_out);
350 
359 nmbs_error nmbs_read_input_registers(nmbs_t* nmbs, uint16_t address, uint16_t quantity, uint16_t* registers_out);
360 
368 nmbs_error nmbs_write_single_coil(nmbs_t* nmbs, uint16_t address, bool value);
369 
377 nmbs_error nmbs_write_single_register(nmbs_t* nmbs, uint16_t address, uint16_t value);
378 
387 nmbs_error nmbs_write_multiple_coils(nmbs_t* nmbs, uint16_t address, uint16_t quantity, const nmbs_bitfield coils);
388 
397 nmbs_error nmbs_write_multiple_registers(nmbs_t* nmbs, uint16_t address, uint16_t quantity, const uint16_t* registers);
398 
408 nmbs_error nmbs_read_file_record(nmbs_t* nmbs, uint16_t file_number, uint16_t record_number, uint16_t* registers,
409  uint16_t count);
410 
420 nmbs_error nmbs_write_file_record(nmbs_t* nmbs, uint16_t file_number, uint16_t record_number, const uint16_t* registers,
421  uint16_t count);
422 
434 nmbs_error nmbs_read_write_registers(nmbs_t* nmbs, uint16_t read_address, uint16_t read_quantity,
435  uint16_t* registers_out, uint16_t write_address, uint16_t write_quantity,
436  const uint16_t* registers);
437 
447 nmbs_error nmbs_read_device_identification_basic(nmbs_t* nmbs, char* vendor_name, char* product_code,
448  char* major_minor_revision, uint8_t buffer_length);
449 
460 nmbs_error nmbs_read_device_identification_regular(nmbs_t* nmbs, char* vendor_url, char* product_name, char* model_name,
461  char* user_application_name, uint8_t buffer_length);
462 
475 nmbs_error nmbs_read_device_identification_extended(nmbs_t* nmbs, uint8_t object_id_start, uint8_t* ids, char** buffers,
476  uint8_t ids_length, uint8_t buffer_length,
477  uint8_t* objects_count_out);
478 
487 nmbs_error nmbs_read_device_identification(nmbs_t* nmbs, uint8_t object_id, char* buffer, uint8_t buffer_length);
488 
498 nmbs_error nmbs_send_raw_pdu(nmbs_t* nmbs, uint8_t fc, const uint8_t* data, uint16_t data_len);
499 
507 nmbs_error nmbs_receive_raw_pdu_response(nmbs_t* nmbs, uint8_t* data_out, uint8_t data_out_len);
508 #endif
509 
514 uint16_t nmbs_crc_calc(const uint8_t* data, uint32_t length);
515 
516 #ifndef NMBS_STRERROR_DISABLED
522 const char* nmbs_strerror(nmbs_error error);
523 #endif
524 
525 #ifdef __cplusplus
526 } // extern "C"
527 #endif
528 
529 #endif //NANOMODBUS_H
nmbs_error nmbs_read_input_registers(nmbs_t *nmbs, uint16_t address, uint16_t quantity, uint16_t *registers_out)
Definition: nanomodbus.c:1955
nmbs_error
Definition: nanomodbus.h:55
@ NMBS_ERROR_INVALID_UNIT_ID
Definition: nanomodbus.h:58
@ NMBS_ERROR_NONE
Definition: nanomodbus.h:65
@ NMBS_ERROR_INVALID_ARGUMENT
Definition: nanomodbus.h:64
@ NMBS_EXCEPTION_ILLEGAL_DATA_ADDRESS
Definition: nanomodbus.h:69
@ NMBS_ERROR_TRANSPORT
Definition: nanomodbus.h:61
@ NMBS_ERROR_INVALID_TCP_MBAP
Definition: nanomodbus.h:59
@ NMBS_ERROR_INVALID_REQUEST
Definition: nanomodbus.h:57
@ NMBS_ERROR_INVALID_RESPONSE
Definition: nanomodbus.h:63
@ NMBS_EXCEPTION_ILLEGAL_DATA_VALUE
Definition: nanomodbus.h:70
@ NMBS_ERROR_TIMEOUT
Definition: nanomodbus.h:62
@ NMBS_EXCEPTION_ILLEGAL_FUNCTION
Definition: nanomodbus.h:68
@ NMBS_EXCEPTION_SERVER_DEVICE_FAILURE
Definition: nanomodbus.h:71
@ NMBS_ERROR_CRC
Definition: nanomodbus.h:60
uint8_t nmbs_bitfield[250]
Definition: nanomodbus.h:85
nmbs_error nmbs_write_multiple_registers(nmbs_t *nmbs, uint16_t address, uint16_t quantity, const uint16_t *registers)
Definition: nanomodbus.c:2036
nmbs_error nmbs_write_single_register(nmbs_t *nmbs, uint16_t address, uint16_t value)
Definition: nanomodbus.c:1982
nmbs_error nmbs_send_raw_pdu(nmbs_t *nmbs, uint8_t fc, const uint8_t *data, uint16_t data_len)
Definition: nanomodbus.c:2309
struct nmbs_callbacks nmbs_callbacks
nmbs_error nmbs_client_create(nmbs_t *nmbs, const nmbs_platform_conf *platform_conf)
Definition: nanomodbus.c:1890
void nmbs_set_byte_timeout(nmbs_t *nmbs, int32_t timeout_ms)
Definition: nanomodbus.c:192
nmbs_error nmbs_read_holding_registers(nmbs_t *nmbs, uint16_t address, uint16_t quantity, uint16_t *registers_out)
Definition: nanomodbus.c:1950
void nmbs_set_destination_rtu_address(nmbs_t *nmbs, uint8_t address)
Definition: nanomodbus.c:197
nmbs_error nmbs_read_device_identification_regular(nmbs_t *nmbs, char *vendor_url, char *product_name, char *model_name, char *user_application_name, uint8_t buffer_length)
Definition: nanomodbus.c:2218
nmbs_error nmbs_receive_raw_pdu_response(nmbs_t *nmbs, uint8_t *data_out, uint8_t data_out_len)
Definition: nanomodbus.c:2323
nmbs_error nmbs_server_poll(nmbs_t *nmbs)
Definition: nanomodbus.c:1847
const char * nmbs_strerror(nmbs_error error)
Definition: nanomodbus.c:2351
nmbs_error nmbs_write_file_record(nmbs_t *nmbs, uint16_t file_number, uint16_t record_number, const uint16_t *registers, uint16_t count)
Definition: nanomodbus.c:2100
nmbs_error nmbs_write_multiple_coils(nmbs_t *nmbs, uint16_t address, uint16_t quantity, const nmbs_bitfield coils)
Definition: nanomodbus.c:2002
void nmbs_set_callbacks_arg(nmbs_t *nmbs, void *arg)
Definition: nanomodbus.c:1883
nmbs_error nmbs_read_device_identification_extended(nmbs_t *nmbs, uint8_t object_id_start, uint8_t *ids, char **buffers, uint8_t ids_length, uint8_t buffer_length, uint8_t *objects_count_out)
Definition: nanomodbus.c:2254
nmbs_error nmbs_server_create(nmbs_t *nmbs, uint8_t address_rtu, const nmbs_platform_conf *platform_conf, const nmbs_callbacks *callbacks)
Definition: nanomodbus.c:1831
nmbs_error nmbs_read_coils(nmbs_t *nmbs, uint16_t address, uint16_t quantity, nmbs_bitfield coils_out)
Definition: nanomodbus.c:1918
nmbs_error nmbs_read_file_record(nmbs_t *nmbs, uint16_t file_number, uint16_t record_number, uint16_t *registers, uint16_t count)
Definition: nanomodbus.c:2070
void nmbs_set_read_timeout(nmbs_t *nmbs, int32_t timeout_ms)
Definition: nanomodbus.c:187
void nmbs_set_platform_arg(nmbs_t *nmbs, void *arg)
Definition: nanomodbus.c:202
nmbs_error nmbs_read_write_registers(nmbs_t *nmbs, uint16_t read_address, uint16_t read_quantity, uint16_t *registers_out, uint16_t write_address, uint16_t write_quantity, const uint16_t *registers)
Definition: nanomodbus.c:2135
nmbs_transport
Definition: nanomodbus.h:121
struct nmbs_platform_conf nmbs_platform_conf
uint8_t nmbs_bitfield_256[32]
Definition: nanomodbus.h:90
nmbs_error nmbs_write_single_coil(nmbs_t *nmbs, uint16_t address, bool value)
Definition: nanomodbus.c:1960
uint16_t nmbs_crc_calc(const uint8_t *data, uint32_t length)
Definition: nanomodbus.c:207
struct nmbs_t nmbs_t
nmbs_error nmbs_read_device_identification_basic(nmbs_t *nmbs, char *vendor_name, char *product_code, char *major_minor_revision, uint8_t buffer_length)
Definition: nanomodbus.c:2182
nmbs_error nmbs_read_discrete_inputs(nmbs_t *nmbs, uint16_t address, uint16_t quantity, nmbs_bitfield inputs_out)
Definition: nanomodbus.c:1923
nmbs_error nmbs_read_device_identification(nmbs_t *nmbs, uint8_t object_id, char *buffer, uint8_t buffer_length)
Definition: nanomodbus.c:2290
Definition: nanomodbus.h:164
Definition: nanomodbus.h:146
int32_t(* read)(uint8_t *buf, uint16_t count, int32_t byte_timeout_ms, void *arg)
Definition: nanomodbus.h:148
void * arg
Definition: nanomodbus.h:152
nmbs_transport transport
Definition: nanomodbus.h:147
int32_t(* write)(const uint8_t *buf, uint16_t count, int32_t byte_timeout_ms, void *arg)
Definition: nanomodbus.h:150
Definition: nanomodbus.h:228