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) 2024 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
46#ifdef __cplusplus
47extern "C" {
48#endif
49
54typedef enum nmbs_error {
55 // Library errors
66 // Modbus exceptions
72
73
78#define nmbs_error_is_exception(e) ((e) > 0 && (e) < 5)
79
80
84typedef uint8_t nmbs_bitfield[250];
85
89typedef uint8_t nmbs_bitfield_256[32];
90
94#define nmbs_bitfield_read(bf, b) ((bool) ((bf)[(b) / 8] & (0x1 << ((b) % 8))))
95
99#define nmbs_bitfield_set(bf, b) (((bf)[(b) / 8]) = (((bf)[(b) / 8]) | (0x1 << ((b) % 8))))
100
104#define nmbs_bitfield_unset(bf, b) (((bf)[(b) / 8]) = (((bf)[(b) / 8]) & ~(0x1 << ((b) % 8))))
105
109#define nmbs_bitfield_write(bf, b, v) \
110 (((bf)[(b) / 8]) = ((v) ? (((bf)[(b) / 8]) | (0x1 << ((b) % 8))) : (((bf)[(b) / 8]) & ~(0x1 << ((b) % 8)))))
111
115#define nmbs_bitfield_reset(bf) memset(bf, 0, sizeof(bf))
116
120typedef enum nmbs_transport {
121 NMBS_TRANSPORT_RTU = 1,
122 NMBS_TRANSPORT_TCP = 2,
124
125
147typedef struct nmbs_platform_conf {
149 int32_t (*read)(uint8_t* buf, uint16_t count, int32_t byte_timeout_ms,
150 void* arg);
151 int32_t (*write)(const uint8_t* buf, uint16_t count, int32_t byte_timeout_ms,
152 void* arg);
153 uint16_t (*crc_calc)(const uint8_t* data, uint32_t length,
154 void* arg);
155 void* arg;
156 uint32_t initialized;
158
159
168typedef struct nmbs_callbacks {
169#ifndef NMBS_SERVER_DISABLED
170#ifndef NMBS_SERVER_READ_COILS_DISABLED
171 nmbs_error (*read_coils)(uint16_t address, uint16_t quantity, nmbs_bitfield coils_out, uint8_t unit_id, void* arg);
172#endif
173
174#ifndef NMBS_SERVER_READ_DISCRETE_INPUTS_DISABLED
175 nmbs_error (*read_discrete_inputs)(uint16_t address, uint16_t quantity, nmbs_bitfield inputs_out, uint8_t unit_id,
176 void* arg);
177#endif
178
179#ifndef NMBS_SERVER_READ_HOLDING_REGISTERS_DISABLED
180 nmbs_error (*read_holding_registers)(uint16_t address, uint16_t quantity, uint16_t* registers_out, uint8_t unit_id,
181 void* arg);
182#endif
183
184#ifndef NMBS_SERVER_READ_INPUT_REGISTERS_DISABLED
185 nmbs_error (*read_input_registers)(uint16_t address, uint16_t quantity, uint16_t* registers_out, uint8_t unit_id,
186 void* arg);
187#endif
188
189#ifndef NMBS_SERVER_WRITE_SINGLE_COIL_DISABLED
190 nmbs_error (*write_single_coil)(uint16_t address, bool value, uint8_t unit_id, void* arg);
191#endif
192
193#ifndef NMBS_SERVER_WRITE_SINGLE_REGISTER_DISABLED
194 nmbs_error (*write_single_register)(uint16_t address, uint16_t value, uint8_t unit_id, void* arg);
195#endif
196
197#ifndef NMBS_SERVER_WRITE_MULTIPLE_COILS_DISABLED
198 nmbs_error (*write_multiple_coils)(uint16_t address, uint16_t quantity, const nmbs_bitfield coils, uint8_t unit_id,
199 void* arg);
200#endif
201
202#ifndef NMBS_SERVER_WRITE_MULTIPLE_REGISTERS_DISABLED
203 nmbs_error (*write_multiple_registers)(uint16_t address, uint16_t quantity, const uint16_t* registers,
204 uint8_t unit_id, void* arg);
205#endif
206
207#ifndef NMBS_SERVER_READ_FILE_RECORD_DISABLED
208 nmbs_error (*read_file_record)(uint16_t file_number, uint16_t record_number, uint16_t* registers, uint16_t count,
209 uint8_t unit_id, void* arg);
210#endif
211
212#ifndef NMBS_SERVER_WRITE_FILE_RECORD_DISABLED
213 nmbs_error (*write_file_record)(uint16_t file_number, uint16_t record_number, const uint16_t* registers,
214 uint16_t count, uint8_t unit_id, void* arg);
215#endif
216
217#ifndef NMBS_SERVER_READ_DEVICE_IDENTIFICATION_DISABLED
218#define NMBS_DEVICE_IDENTIFICATION_STRING_LENGTH 128
219 nmbs_error (*read_device_identification)(uint8_t object_id, char buffer[NMBS_DEVICE_IDENTIFICATION_STRING_LENGTH]);
220 nmbs_error (*read_device_identification_map)(nmbs_bitfield_256 map);
221#endif
222#endif
223
224 void* arg; // User data, will be passed to functions above
225 uint32_t initialized; // Reserved, workaround for older user code not calling nmbs_callbacks_create()
227
228
233typedef struct nmbs_t {
234 struct {
235 uint8_t buf[260];
236 uint16_t buf_idx;
237
238 uint8_t unit_id;
239 uint8_t fc;
240 uint16_t transaction_id;
241 bool broadcast;
242 bool ignored;
243 } msg;
244
245 nmbs_callbacks callbacks;
246
247 int32_t byte_timeout_ms;
248 int32_t read_timeout_ms;
249
250 nmbs_platform_conf platform;
251
252 uint8_t address_rtu;
253 uint8_t dest_address_rtu;
254 uint16_t current_tid;
256
260static const uint8_t NMBS_BROADCAST_ADDRESS = 0;
261
269void nmbs_set_read_timeout(nmbs_t* nmbs, int32_t timeout_ms);
270
275void nmbs_set_byte_timeout(nmbs_t* nmbs, int32_t timeout_ms);
276
281
286void nmbs_set_platform_arg(nmbs_t* nmbs, void* arg);
287
288#ifndef NMBS_SERVER_DISABLED
293
302nmbs_error nmbs_server_create(nmbs_t* nmbs, uint8_t address_rtu, const nmbs_platform_conf* platform_conf,
303 const nmbs_callbacks* callbacks);
304
313
318void nmbs_set_callbacks_arg(nmbs_t* nmbs, void* arg);
319#endif
320
321#ifndef NMBS_CLIENT_DISABLED
328nmbs_error nmbs_client_create(nmbs_t* nmbs, const nmbs_platform_conf* platform_conf);
329
334void nmbs_set_destination_rtu_address(nmbs_t* nmbs, uint8_t address);
335
344nmbs_error nmbs_read_coils(nmbs_t* nmbs, uint16_t address, uint16_t quantity, nmbs_bitfield coils_out);
345
354nmbs_error nmbs_read_discrete_inputs(nmbs_t* nmbs, uint16_t address, uint16_t quantity, nmbs_bitfield inputs_out);
355
364nmbs_error nmbs_read_holding_registers(nmbs_t* nmbs, uint16_t address, uint16_t quantity, uint16_t* registers_out);
365
374nmbs_error nmbs_read_input_registers(nmbs_t* nmbs, uint16_t address, uint16_t quantity, uint16_t* registers_out);
375
383nmbs_error nmbs_write_single_coil(nmbs_t* nmbs, uint16_t address, bool value);
384
392nmbs_error nmbs_write_single_register(nmbs_t* nmbs, uint16_t address, uint16_t value);
393
402nmbs_error nmbs_write_multiple_coils(nmbs_t* nmbs, uint16_t address, uint16_t quantity, const nmbs_bitfield coils);
403
412nmbs_error nmbs_write_multiple_registers(nmbs_t* nmbs, uint16_t address, uint16_t quantity, const uint16_t* registers);
413
423nmbs_error nmbs_read_file_record(nmbs_t* nmbs, uint16_t file_number, uint16_t record_number, uint16_t* registers,
424 uint16_t count);
425
435nmbs_error nmbs_write_file_record(nmbs_t* nmbs, uint16_t file_number, uint16_t record_number, const uint16_t* registers,
436 uint16_t count);
437
449nmbs_error nmbs_read_write_registers(nmbs_t* nmbs, uint16_t read_address, uint16_t read_quantity,
450 uint16_t* registers_out, uint16_t write_address, uint16_t write_quantity,
451 const uint16_t* registers);
452
462nmbs_error nmbs_read_device_identification_basic(nmbs_t* nmbs, char* vendor_name, char* product_code,
463 char* major_minor_revision, uint8_t buffers_length);
464
475nmbs_error nmbs_read_device_identification_regular(nmbs_t* nmbs, char* vendor_url, char* product_name, char* model_name,
476 char* user_application_name, uint8_t buffers_length);
477
490nmbs_error nmbs_read_device_identification_extended(nmbs_t* nmbs, uint8_t object_id_start, uint8_t* ids, char** buffers,
491 uint8_t ids_length, uint8_t buffer_length,
492 uint8_t* objects_count_out);
493
502nmbs_error nmbs_read_device_identification(nmbs_t* nmbs, uint8_t object_id, char* buffer, uint8_t buffer_length);
503
513nmbs_error nmbs_send_raw_pdu(nmbs_t* nmbs, uint8_t fc, const uint8_t* data, uint16_t data_len);
514
522nmbs_error nmbs_receive_raw_pdu_response(nmbs_t* nmbs, uint8_t* data_out, uint8_t data_out_len);
523#endif
524
529uint16_t nmbs_crc_calc(const uint8_t* data, uint32_t length, void* arg);
530
531#ifndef NMBS_STRERROR_DISABLED
537const char* nmbs_strerror(nmbs_error error);
538#endif
539
540#ifdef __cplusplus
541} // extern "C"
542#endif
543
544#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:1986
nmbs_error
Definition: nanomodbus.h:54
@ NMBS_ERROR_INVALID_UNIT_ID
Definition: nanomodbus.h:57
@ NMBS_ERROR_NONE
Definition: nanomodbus.h:64
@ NMBS_ERROR_INVALID_ARGUMENT
Definition: nanomodbus.h:63
@ NMBS_EXCEPTION_ILLEGAL_DATA_ADDRESS
Definition: nanomodbus.h:68
@ NMBS_ERROR_TRANSPORT
Definition: nanomodbus.h:60
@ NMBS_ERROR_INVALID_TCP_MBAP
Definition: nanomodbus.h:58
@ NMBS_ERROR_INVALID_REQUEST
Definition: nanomodbus.h:56
@ NMBS_ERROR_INVALID_RESPONSE
Definition: nanomodbus.h:62
@ NMBS_EXCEPTION_ILLEGAL_DATA_VALUE
Definition: nanomodbus.h:69
@ NMBS_ERROR_TIMEOUT
Definition: nanomodbus.h:61
@ NMBS_EXCEPTION_ILLEGAL_FUNCTION
Definition: nanomodbus.h:67
@ NMBS_EXCEPTION_SERVER_DEVICE_FAILURE
Definition: nanomodbus.h:70
@ NMBS_ERROR_CRC
Definition: nanomodbus.h:59
uint8_t nmbs_bitfield[250]
Definition: nanomodbus.h:84
nmbs_error nmbs_write_multiple_registers(nmbs_t *nmbs, uint16_t address, uint16_t quantity, const uint16_t *registers)
Definition: nanomodbus.c:2067
nmbs_error nmbs_write_single_register(nmbs_t *nmbs, uint16_t address, uint16_t value)
Definition: nanomodbus.c:2013
nmbs_error nmbs_send_raw_pdu(nmbs_t *nmbs, uint8_t fc, const uint8_t *data, uint16_t data_len)
Definition: nanomodbus.c:2340
struct nmbs_callbacks nmbs_callbacks
void nmbs_callbacks_create(nmbs_callbacks *callbacks)
Definition: nanomodbus.c:1853
nmbs_error nmbs_client_create(nmbs_t *nmbs, const nmbs_platform_conf *platform_conf)
Definition: nanomodbus.c:1921
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 buffers_length)
Definition: nanomodbus.c:2249
void nmbs_set_byte_timeout(nmbs_t *nmbs, int32_t timeout_ms)
Definition: nanomodbus.c:203
nmbs_error nmbs_read_holding_registers(nmbs_t *nmbs, uint16_t address, uint16_t quantity, uint16_t *registers_out)
Definition: nanomodbus.c:1981
void nmbs_set_destination_rtu_address(nmbs_t *nmbs, uint8_t address)
Definition: nanomodbus.c:216
nmbs_error nmbs_receive_raw_pdu_response(nmbs_t *nmbs, uint8_t *data_out, uint8_t data_out_len)
Definition: nanomodbus.c:2354
nmbs_error nmbs_server_poll(nmbs_t *nmbs)
Definition: nanomodbus.c:1878
const char * nmbs_strerror(nmbs_error error)
Definition: nanomodbus.c:2382
nmbs_error nmbs_read_device_identification_basic(nmbs_t *nmbs, char *vendor_name, char *product_code, char *major_minor_revision, uint8_t buffers_length)
Definition: nanomodbus.c:2213
void nmbs_platform_conf_create(nmbs_platform_conf *platform_conf)
Definition: nanomodbus.c:208
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:2131
nmbs_error nmbs_write_multiple_coils(nmbs_t *nmbs, uint16_t address, uint16_t quantity, const nmbs_bitfield coils)
Definition: nanomodbus.c:2033
void nmbs_set_callbacks_arg(nmbs_t *nmbs, void *arg)
Definition: nanomodbus.c:1914
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:2285
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:1859
nmbs_error nmbs_read_coils(nmbs_t *nmbs, uint16_t address, uint16_t quantity, nmbs_bitfield coils_out)
Definition: nanomodbus.c:1949
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:2101
void nmbs_set_read_timeout(nmbs_t *nmbs, int32_t timeout_ms)
Definition: nanomodbus.c:198
void nmbs_set_platform_arg(nmbs_t *nmbs, void *arg)
Definition: nanomodbus.c:221
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:2166
uint16_t nmbs_crc_calc(const uint8_t *data, uint32_t length, void *arg)
Definition: nanomodbus.c:226
nmbs_transport
Definition: nanomodbus.h:120
struct nmbs_platform_conf nmbs_platform_conf
uint8_t nmbs_bitfield_256[32]
Definition: nanomodbus.h:89
nmbs_error nmbs_write_single_coil(nmbs_t *nmbs, uint16_t address, bool value)
Definition: nanomodbus.c:1991
struct nmbs_t nmbs_t
nmbs_error nmbs_read_discrete_inputs(nmbs_t *nmbs, uint16_t address, uint16_t quantity, nmbs_bitfield inputs_out)
Definition: nanomodbus.c:1954
nmbs_error nmbs_read_device_identification(nmbs_t *nmbs, uint8_t object_id, char *buffer, uint8_t buffer_length)
Definition: nanomodbus.c:2321
Definition: nanomodbus.h:168
Definition: nanomodbus.h:147
int32_t(* read)(uint8_t *buf, uint16_t count, int32_t byte_timeout_ms, void *arg)
Definition: nanomodbus.h:149
uint32_t initialized
Definition: nanomodbus.h:156
uint16_t(* crc_calc)(const uint8_t *data, uint32_t length, void *arg)
Definition: nanomodbus.h:153
void * arg
Definition: nanomodbus.h:155
nmbs_transport transport
Definition: nanomodbus.h:148
int32_t(* write)(const uint8_t *buf, uint16_t count, int32_t byte_timeout_ms, void *arg)
Definition: nanomodbus.h:151
Definition: nanomodbus.h:233