11#if PC_ENABLE_MODBUS_MASTER
13size_t pc_modbus_build_read(uint8_t fc, uint16_t txid, uint8_t unit, uint16_t start, uint16_t count, uint8_t *out,
20 if (fc != 0x03 && fc != 0x04)
24 if (count < 1 || count > 125)
30 out[0] = (uint8_t)(txid >> 8);
31 out[1] = (uint8_t)(txid & 0xFF);
39 out[8] = (uint8_t)(start >> 8);
40 out[9] = (uint8_t)(start & 0xFF);
41 out[10] = (uint8_t)(count >> 8);
42 out[11] = (uint8_t)(count & 0xFF);
46int pc_modbus_parse_response(
const uint8_t *adu,
size_t len, uint16_t *regs_out,
size_t max_regs,
47 uint8_t *exception_out)
57 if (adu[2] != 0 || adu[3] != 0)
67 *exception_out = adu[8];
71 if (fc != 0x03 && fc != 0x04 && fc != 0x17)
76 uint8_t byte_count = adu[8];
77 if ((byte_count & 1) || len < (
size_t)(9 + byte_count))
82 int nregs = byte_count / 2;
84 for (
int i = 0; i < nregs && (size_t)i < max_regs; i++)
88 regs_out[i] = (uint16_t)((adu[9 + i * 2] << 8) | adu[9 + i * 2 + 1]);
95size_t pc_modbus_build_read_bits(uint8_t fc, uint16_t txid, uint8_t unit, uint16_t start, uint16_t count, uint8_t *out,
102 if (fc != 0x01 && fc != 0x02)
106 if (count < 1 || count > 2000)
112 out[0] = (uint8_t)(txid >> 8);
113 out[1] = (uint8_t)(txid & 0xFF);
120 out[8] = (uint8_t)(start >> 8);
121 out[9] = (uint8_t)(start & 0xFF);
122 out[10] = (uint8_t)(count >> 8);
123 out[11] = (uint8_t)(count & 0xFF);
127int pc_modbus_parse_read_bits_response(
const uint8_t *adu,
size_t len, uint16_t count, uint8_t *bits_out,
128 size_t max_bits, uint8_t *exception_out)
138 if (adu[2] != 0 || adu[3] != 0)
148 *exception_out = adu[8];
152 if (fc != 0x01 && fc != 0x02)
156 if (count < 1 || count > 2000)
161 uint8_t byte_count = adu[8];
162 uint16_t expect_bytes = (uint16_t)((count + 7) / 8);
163 if (byte_count != expect_bytes || len < (
size_t)(9 + byte_count))
169 for (uint16_t i = 0; i < count && (size_t)i < max_bits; i++)
171 uint8_t
byte = adu[9 + (i / 8)];
174 bits_out[i] = (uint8_t)((
byte >> (i % 8)) & 1);
181size_t pc_modbus_build_write_single_coil(uint16_t txid, uint8_t unit, uint16_t addr,
bool on, uint8_t *out,
size_t cap)
183 if (!out || cap < 12)
188 out[0] = (uint8_t)(txid >> 8);
189 out[1] = (uint8_t)(txid & 0xFF);
197 out[8] = (uint8_t)(addr >> 8);
198 out[9] = (uint8_t)(addr & 0xFF);
199 out[10] = on ? 0xFF : 0x00;
204size_t pc_modbus_build_write_multiple_coils(uint16_t txid, uint8_t unit, uint16_t start,
const uint8_t *bits,
205 uint16_t count, uint8_t *out,
size_t cap)
211 if (count < 1 || count > 1968)
216 uint8_t byte_count = (uint8_t)((count + 7) / 8);
217 size_t pdu_len = 6u + (size_t)byte_count;
218 size_t total = 7u + pdu_len;
224 uint16_t mbap_len = (uint16_t)(1u + pdu_len);
225 out[0] = (uint8_t)(txid >> 8);
226 out[1] = (uint8_t)(txid & 0xFF);
229 out[4] = (uint8_t)(mbap_len >> 8);
230 out[5] = (uint8_t)(mbap_len & 0xFF);
234 out[8] = (uint8_t)(start >> 8);
235 out[9] = (uint8_t)(start & 0xFF);
236 out[10] = (uint8_t)(count >> 8);
237 out[11] = (uint8_t)(count & 0xFF);
238 out[12] = byte_count;
239 for (uint16_t i = 0; i < byte_count; i++)
243 for (uint16_t i = 0; i < count; i++)
247 out[13 + (i / 8)] |= (uint8_t)(1u << (i % 8));
253size_t pc_modbus_build_write_single(uint16_t txid, uint8_t unit, uint16_t addr, uint16_t value, uint8_t *out,
256 if (!out || cap < 12)
262 out[0] = (uint8_t)(txid >> 8);
263 out[1] = (uint8_t)(txid & 0xFF);
271 out[8] = (uint8_t)(addr >> 8);
272 out[9] = (uint8_t)(addr & 0xFF);
273 out[10] = (uint8_t)(value >> 8);
274 out[11] = (uint8_t)(value & 0xFF);
278size_t pc_modbus_build_write_multiple(uint16_t txid, uint8_t unit, uint16_t start,
const uint16_t *values,
279 uint16_t count, uint8_t *out,
size_t cap)
285 if (count < 1 || count > 123)
290 uint8_t byte_count = (uint8_t)(count * 2);
291 size_t pdu_len = 6u + (size_t)byte_count;
292 size_t total = 7u + pdu_len;
299 uint16_t mbap_len = (uint16_t)(1u + pdu_len);
300 out[0] = (uint8_t)(txid >> 8);
301 out[1] = (uint8_t)(txid & 0xFF);
304 out[4] = (uint8_t)(mbap_len >> 8);
305 out[5] = (uint8_t)(mbap_len & 0xFF);
309 out[8] = (uint8_t)(start >> 8);
310 out[9] = (uint8_t)(start & 0xFF);
311 out[10] = (uint8_t)(count >> 8);
312 out[11] = (uint8_t)(count & 0xFF);
313 out[12] = byte_count;
314 for (uint16_t i = 0; i < count; i++)
316 out[13 + i * 2] = (uint8_t)(values[i] >> 8);
317 out[13 + i * 2 + 1] = (uint8_t)(values[i] & 0xFF);
322int pc_modbus_parse_write_response(
const uint8_t *adu,
size_t len, uint16_t *addr_out, uint8_t *exception_out)
336 if (adu[2] != 0 || adu[3] != 0)
346 *exception_out = adu[8];
350 if (fc != 0x05 && fc != 0x06 && fc != 0x0F && fc != 0x10)
361 *addr_out = (uint16_t)((adu[8] << 8) | adu[9]);
363 uint16_t tail = (uint16_t)((adu[10] << 8) | adu[11]);
364 bool single = (fc == 0x05 || fc == 0x06);
365 return single ? 1 : (int)tail;
368size_t pc_modbus_build_mask_write(uint16_t txid, uint8_t unit, uint16_t addr, uint16_t and_mask, uint16_t or_mask,
369 uint8_t *out,
size_t cap)
371 if (!out || cap < 14)
376 out[0] = (uint8_t)(txid >> 8);
377 out[1] = (uint8_t)(txid & 0xFF);
385 out[8] = (uint8_t)(addr >> 8);
386 out[9] = (uint8_t)(addr & 0xFF);
387 out[10] = (uint8_t)(and_mask >> 8);
388 out[11] = (uint8_t)(and_mask & 0xFF);
389 out[12] = (uint8_t)(or_mask >> 8);
390 out[13] = (uint8_t)(or_mask & 0xFF);
394size_t pc_modbus_build_read_write_multiple(uint16_t txid, uint8_t unit, uint16_t read_start, uint16_t read_count,
395 uint16_t write_start,
const uint16_t *values, uint16_t write_count,
396 uint8_t *out,
size_t cap)
402 if (read_count < 1 || read_count > 125 || write_count < 1 || write_count > 121)
407 uint8_t byte_count = (uint8_t)(write_count * 2);
408 size_t pdu_len = 10u + (size_t)byte_count;
409 size_t total = 7u + pdu_len;
415 uint16_t mbap_len = (uint16_t)(1u + pdu_len);
416 out[0] = (uint8_t)(txid >> 8);
417 out[1] = (uint8_t)(txid & 0xFF);
420 out[4] = (uint8_t)(mbap_len >> 8);
421 out[5] = (uint8_t)(mbap_len & 0xFF);
425 out[8] = (uint8_t)(read_start >> 8);
426 out[9] = (uint8_t)(read_start & 0xFF);
427 out[10] = (uint8_t)(read_count >> 8);
428 out[11] = (uint8_t)(read_count & 0xFF);
429 out[12] = (uint8_t)(write_start >> 8);
430 out[13] = (uint8_t)(write_start & 0xFF);
431 out[14] = (uint8_t)(write_count >> 8);
432 out[15] = (uint8_t)(write_count & 0xFF);
433 out[16] = byte_count;
434 for (uint16_t i = 0; i < write_count; i++)
436 out[17 + i * 2] = (uint8_t)(values[i] >> 8);
437 out[17 + i * 2 + 1] = (uint8_t)(values[i] & 0xFF);
442int pc_modbus_parse_mask_write_response(
const uint8_t *adu,
size_t len, uint16_t *addr_out, uint16_t *and_out,
443 uint16_t *or_out, uint8_t *exception_out)
453 if (adu[2] != 0 || adu[3] != 0)
462 *exception_out = adu[8];
466 if (fc != 0x16 || len < 14)
472 *addr_out = (uint16_t)((adu[8] << 8) | adu[9]);
476 *and_out = (uint16_t)((adu[10] << 8) | adu[11]);
480 *or_out = (uint16_t)((adu[12] << 8) | adu[13]);