2 * Generic MODBUS Library for STM32
4 * (c) 2019 Martin Mareš <mj@ucw.cz>
13 #include <libopencm3/cm3/nvic.h>
14 #include <libopencm3/stm32/gpio.h>
15 #include <libopencm3/stm32/usart.h>
16 #include <libopencm3/stm32/timer.h>
18 /*** Configuration ***/
20 // You should set the following parameters in config.h
22 // USART (pins are expected to be configured by the caller)
23 // #define MODBUS_USART USART2
24 // #define MODBUS_NVIC_USART_IRQ NVIC_USART2_IRQ
25 // #define MODBUS_USART_ISR usart2_isr
27 // GPIO pin for transmitter enable (pins is expected to be configured by the caller)
28 // #define MODBUS_TXEN_GPIO_PORT GPIOA
29 // #define MODBUS_TXEN_GPIO_PIN GPIO1
32 // #define MODBUS_TIMER TIM2
33 // #define MODBUS_NVIC_TIMER_IRQ NVIC_TIM2_IRQ
34 // #define MODBUS_TIMER_ISR tim2_isr
36 // Slave address we are responding at
37 // #define MODBUS_OUR_ADDRESS 42
40 #ifndef MODBUS_BAUD_RATE
41 #define MODBUS_BAUD_RATE 19200
44 // CPU clock frequency
45 // #define CPU_CLOCK_MHZ 72
47 // Receive buffer size (standard specifies 256 bytes, you can make it shorter if necessary)
48 #ifndef MODBUS_RX_BUFSIZE
49 #define MODBUS_RX_BUFSIZE 256
52 // Transmit buffer size (standard specifies 256 bytes, you can make it shorter if necessary)
53 #ifndef MODBUS_TX_BUFSIZE
54 #define MODBUS_TX_BUFSIZE 256
57 // Receive timeout in microseconds
58 #ifndef MODBUS_RX_TIMEOUT
59 #if MODBUS_BAUD_RATE <= 19200
60 // For low baud rates, the standard specifies timeout of 1.5 character times
61 // (1 character = start bit + 8 data bits + parity bit + stop bit = 11 bits)
62 #define MODBUS_RX_TIMEOUT (1000000*11*3/2/MODBUS_BAUD_RATE)
64 // For high rates, the timeout is fixed to 750 μs
65 #define MODBUS_RX_TIMEOUT 750
70 // #define MODBUS_DEBUG
73 #define DEBUG debug_printf
75 #define DEBUG(xxx, ...) do { } while (0)
88 static byte rx_buf[MODBUS_RX_BUFSIZE];
91 static byte state; // STATE_xxx
93 static byte *rx_frame;
94 static byte *rx_frame_end;
96 static byte tx_buf[MODBUS_TX_BUFSIZE];
100 static bool check_frame(void);
101 static void process_frame(void);
103 /*** Low-level layer ***/
105 static void rx_init(void)
110 usart_set_mode(MODBUS_USART, USART_MODE_RX);
111 usart_enable_rx_interrupt(MODBUS_USART);
115 static void rx_done(void)
117 state = STATE_RX_DONE;
118 usart_disable_rx_interrupt(MODBUS_USART);
121 static void tx_init(void)
125 gpio_set(MODBUS_TXEN_GPIO_PORT, MODBUS_TXEN_GPIO_PIN);
126 usart_set_mode(MODBUS_USART, USART_MODE_TX);
127 usart_enable_tx_interrupt(MODBUS_USART);
130 static void tx_done(void)
132 state = STATE_TX_DONE;
133 // usart_disable_tx_interrupt(MODBUS_USART); // Already done by irq handler
134 gpio_clear(MODBUS_TXEN_GPIO_PORT, MODBUS_TXEN_GPIO_PIN);
137 void modbus_init(void)
139 DEBUG("MODBUS: Init\n");
141 timer_set_prescaler(MODBUS_TIMER, CPU_CLOCK_MHZ-1); // 1 tick = 1 μs
142 timer_set_mode(MODBUS_TIMER, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_DOWN);
143 timer_update_on_overflow(MODBUS_TIMER);
144 timer_disable_preload(MODBUS_TIMER);
145 timer_one_shot_mode(MODBUS_TIMER);
146 timer_enable_irq(MODBUS_TIMER, TIM_DIER_UIE);
147 nvic_enable_irq(MODBUS_NVIC_TIMER_IRQ);
149 gpio_clear(MODBUS_TXEN_GPIO_PORT, MODBUS_TXEN_GPIO_PIN);
151 usart_set_baudrate(MODBUS_USART, MODBUS_BAUD_RATE);
152 usart_set_databits(MODBUS_USART, 9);
153 usart_set_stopbits(MODBUS_USART, USART_STOPBITS_1);
154 usart_set_parity(MODBUS_USART, USART_PARITY_EVEN);
155 usart_set_flow_control(MODBUS_USART, USART_FLOWCONTROL_NONE);
159 nvic_enable_irq(MODBUS_NVIC_USART_IRQ);
160 usart_enable(MODBUS_USART);
163 void MODBUS_USART_ISR(void)
165 u32 status = USART_SR(MODBUS_USART);
167 if (status & USART_SR_RXNE) {
168 uint ch = usart_recv(MODBUS_USART);
169 if (state == STATE_RX) {
170 if (status & (USART_SR_FE | USART_SR_ORE | USART_SR_NE)) {
172 } else if (rx_size < MODBUS_RX_BUFSIZE) {
174 modbus_frame_start_hook();
175 rx_buf[rx_size++] = ch;
180 timer_set_period(MODBUS_TIMER, MODBUS_RX_TIMEOUT);
181 timer_generate_event(MODBUS_TIMER, TIM_EGR_UG);
182 timer_enable_counter(MODBUS_TIMER);
186 if (state == STATE_TX) {
187 if (status & USART_SR_TXE) {
188 if (tx_pos < tx_size) {
189 usart_send(MODBUS_USART, tx_buf[tx_pos++]);
191 // The transmitter is double-buffered, so at this moment, it is transmitting
192 // the last byte of the frame. Wait until transfer is completed.
193 usart_disable_tx_interrupt(MODBUS_USART);
194 USART_CR1(MODBUS_USART) |= USART_CR1_TCIE;
195 state = STATE_TX_LAST;
198 } else if (state == STATE_TX_LAST) {
199 if (status & USART_SR_TC) {
200 // Transfer of the last byte is complete. Release the bus.
201 USART_CR1(MODBUS_USART) &= ~USART_CR1_TCIE;
208 void MODBUS_TIMER_ISR(void)
210 if (TIM_SR(MODBUS_TIMER) & TIM_SR_UIF) {
211 TIM_SR(MODBUS_TIMER) &= ~TIM_SR_UIF;
212 if (state == STATE_RX)
217 void modbus_loop(void)
219 if (state != STATE_RX_DONE)
221 state = STATE_PROCESSING;
223 if (!check_frame()) {
228 DEBUG("MODBUS: < dest=%02x func=%02x len=%u\n", rx_buf[0], rx_buf[1], rx_size);
230 if (rx_buf[0] == MODBUS_OUR_ADDRESS) {
231 // Frame addressed to us: process and reply
233 DEBUG("MODBUS: > status=%02x len=%u\n", tx_buf[1], tx_size);
235 } else if (rx_buf[0] == 0x00) {
236 // Broadcast frame: process, but do not reply
240 // Somebody else's frame: discard
247 static const byte crc_hi[] = {
248 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0,
249 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
250 0x00, 0xc1, 0x81, 0x40, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0,
251 0x80, 0x41, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40,
252 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1,
253 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0, 0x80, 0x41,
254 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1,
255 0x81, 0x40, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
256 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0,
257 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x00, 0xc1, 0x81, 0x40,
258 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1,
259 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40,
260 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0,
261 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x00, 0xc1, 0x81, 0x40,
262 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0,
263 0x80, 0x41, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40,
264 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0,
265 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
266 0x00, 0xc1, 0x81, 0x40, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0,
267 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
268 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0,
269 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x00, 0xc1, 0x81, 0x40,
270 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1,
271 0x81, 0x40, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
272 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0,
273 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40
276 static const byte crc_lo[] = {
277 0x00, 0xc0, 0xc1, 0x01, 0xc3, 0x03, 0x02, 0xc2, 0xc6, 0x06,
278 0x07, 0xc7, 0x05, 0xc5, 0xc4, 0x04, 0xcc, 0x0c, 0x0d, 0xcd,
279 0x0f, 0xcf, 0xce, 0x0e, 0x0a, 0xca, 0xcb, 0x0b, 0xc9, 0x09,
280 0x08, 0xc8, 0xd8, 0x18, 0x19, 0xd9, 0x1b, 0xdb, 0xda, 0x1a,
281 0x1e, 0xde, 0xdf, 0x1f, 0xdd, 0x1d, 0x1c, 0xdc, 0x14, 0xd4,
282 0xd5, 0x15, 0xd7, 0x17, 0x16, 0xd6, 0xd2, 0x12, 0x13, 0xd3,
283 0x11, 0xd1, 0xd0, 0x10, 0xf0, 0x30, 0x31, 0xf1, 0x33, 0xf3,
284 0xf2, 0x32, 0x36, 0xf6, 0xf7, 0x37, 0xf5, 0x35, 0x34, 0xf4,
285 0x3c, 0xfc, 0xfd, 0x3d, 0xff, 0x3f, 0x3e, 0xfe, 0xfa, 0x3a,
286 0x3b, 0xfb, 0x39, 0xf9, 0xf8, 0x38, 0x28, 0xe8, 0xe9, 0x29,
287 0xeb, 0x2b, 0x2a, 0xea, 0xee, 0x2e, 0x2f, 0xef, 0x2d, 0xed,
288 0xec, 0x2c, 0xe4, 0x24, 0x25, 0xe5, 0x27, 0xe7, 0xe6, 0x26,
289 0x22, 0xe2, 0xe3, 0x23, 0xe1, 0x21, 0x20, 0xe0, 0xa0, 0x60,
290 0x61, 0xa1, 0x63, 0xa3, 0xa2, 0x62, 0x66, 0xa6, 0xa7, 0x67,
291 0xa5, 0x65, 0x64, 0xa4, 0x6c, 0xac, 0xad, 0x6d, 0xaf, 0x6f,
292 0x6e, 0xae, 0xaa, 0x6a, 0x6b, 0xab, 0x69, 0xa9, 0xa8, 0x68,
293 0x78, 0xb8, 0xb9, 0x79, 0xbb, 0x7b, 0x7a, 0xba, 0xbe, 0x7e,
294 0x7f, 0xbf, 0x7d, 0xbd, 0xbc, 0x7c, 0xb4, 0x74, 0x75, 0xb5,
295 0x77, 0xb7, 0xb6, 0x76, 0x72, 0xb2, 0xb3, 0x73, 0xb1, 0x71,
296 0x70, 0xb0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
297 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9c, 0x5c,
298 0x5d, 0x9d, 0x5f, 0x9f, 0x9e, 0x5e, 0x5a, 0x9a, 0x9b, 0x5b,
299 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4b, 0x8b,
300 0x8a, 0x4a, 0x4e, 0x8e, 0x8f, 0x4f, 0x8d, 0x4d, 0x4c, 0x8c,
301 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
302 0x43, 0x83, 0x41, 0x81, 0x80, 0x40
305 static u16 crc16(byte *buf, u16 len)
307 byte hi = 0xff, lo = 0xff;
310 byte i = hi ^ *buf++;
315 return (hi << 8 | lo);
318 /*** High-level layer ***/
320 static bool check_frame(void)
323 // FIXME: Error counters?
324 DEBUG("MODBUS: RX bad\n");
329 // FIXME: Error counters?
330 DEBUG("MODBUS: RX undersize\n");
334 u16 crc = crc16(rx_buf, rx_size - 2);
335 u16 rx_crc = (rx_buf[rx_size-2] << 8) | rx_buf[rx_size-1];
337 // FIXME: Error counters?
338 DEBUG("MODBUS: Bad CRC\n");
342 rx_frame = rx_buf + 1;
343 rx_frame_end = rx_frame + rx_size - 2;
348 FUNC_READ_COILS = 0x01,
349 FUNC_READ_DISCRETE_INPUTS = 0x02,
350 FUNC_READ_HOLDING_REGISTERS = 0x03,
351 FUNC_READ_INPUT_REGISTERS = 0x04,
352 FUNC_WRITE_SINGLE_COIL = 0x05,
353 FUNC_WRITE_SINGLE_REGISTER = 0x06,
354 FUNC_READ_EXCEPTION_STATUS = 0x07,
355 FUNC_DIAGNOSTICS = 0x08,
356 FUNC_GET_COMM_EVENT_COUNTER = 0x0b,
357 FUNC_GET_COMM_EVENT_LOG = 0x0c,
358 FUNC_WRITE_MULTIPLE_COILS = 0x0f,
359 FUNC_WRITE_MULTIPLE_REGISTERS = 0x10,
360 FUNC_REPORT_SLAVE_ID = 0x11,
361 FUNC_READ_FILE_RECORD = 0x14,
362 FUNC_WRITE_FILE_RECORD = 0x15,
363 FUNC_MASK_WRITE_REGISTER = 0x16,
364 FUNC_READ_WRITE_MULTIPLE_REGISTERS = 0x17,
365 FUNC_READ_FIFO_QUEUE = 0x18,
366 FUNC_ENCAPSULATED_INTERFACE_TRANSPORT = 0x2b,
370 ERR_ILLEGAL_FUNCTION = 0x01,
371 ERR_ILLEGAL_DATA_ADDRESS = 0x02,
372 ERR_ILLEGAL_DATA_VALUE = 0x03,
375 static uint read_remains(void)
377 return rx_frame_end - rx_frame;
380 static byte read_byte(void)
385 static u16 read_u16(void)
387 byte hi = *rx_frame++;
388 byte lo = *rx_frame++;
389 return (hi << 8) | lo;
392 static void write_byte(byte v)
394 tx_buf[tx_size++] = v;
397 static void write_u16(u16 v)
403 static bool body_fits(uint body_len)
405 // body_len excludes slave address, function code, and CRC
406 return (2 + body_len + 2 <= MODBUS_TX_BUFSIZE);
409 static void report_error(byte code)
411 // Discard the partially constructed body of the reply and rewrite the header
417 static void func_read_bits(bool coils)
419 if (read_remains() < 4)
420 return report_error(ERR_ILLEGAL_DATA_VALUE);
422 u16 start = read_u16();
423 u16 count = read_u16();
425 uint bytes = (count+7) / 8;
426 if (!body_fits(1 + bytes))
427 return report_error(ERR_ILLEGAL_DATA_VALUE);
429 for (u16 i = 0; i < count; i++)
430 if (!(coils ? modbus_check_coil : modbus_check_discrete_input)(start + i))
431 return report_error(ERR_ILLEGAL_DATA_ADDRESS);
434 for (u16 i = 0; i < bytes; i++) {
436 for (byte j = 0; j < 8 && 8*i + j < count; j++) {
437 uint addr = start + 8*i + j;
438 if ((coils ? modbus_get_coil : modbus_get_discrete_input)(addr))
445 static void func_read_registers(byte holding)
447 if (read_remains() < 4)
448 return report_error(ERR_ILLEGAL_DATA_VALUE);
450 u16 start = read_u16();
451 u16 count = read_u16();
453 uint bytes = 2*count;
454 if (!body_fits(1 + bytes))
455 return report_error(ERR_ILLEGAL_DATA_VALUE);
457 for (u16 i = 0; i < count; i++)
458 if (!(holding ? modbus_check_holding_register : modbus_check_input_register)(start + i))
459 return report_error(ERR_ILLEGAL_DATA_ADDRESS);
461 // FIXME: Reporting of slave failures?
463 for (u16 i = 0; i < count; i++)
464 write_u16((holding ? modbus_get_holding_register : modbus_get_input_register)(start + i));
467 static void func_write_single_coil(void)
469 if (read_remains() < 4)
470 return report_error(ERR_ILLEGAL_DATA_VALUE);
472 u16 addr = read_u16();
473 u16 value = read_u16();
475 if (!modbus_check_coil(addr))
476 return report_error(ERR_ILLEGAL_DATA_ADDRESS);
477 if (value != 0x0000 && value != 0xff00)
478 return report_error(ERR_ILLEGAL_DATA_VALUE);
480 modbus_set_coil(addr, value);
486 static void func_write_single_register(void)
488 if (read_remains() < 4)
489 return report_error(ERR_ILLEGAL_DATA_VALUE);
491 u16 addr = read_u16();
492 u16 value = read_u16();
494 if (!modbus_check_holding_register(addr))
495 return report_error(ERR_ILLEGAL_DATA_ADDRESS);
497 modbus_set_holding_register(addr, value);
503 static void func_write_multiple_coils(void)
505 if (read_remains() < 5)
506 return report_error(ERR_ILLEGAL_DATA_VALUE);
508 u16 start = read_u16();
509 u16 count = read_u16();
510 byte bytes = read_byte();
512 if (read_remains() < bytes || bytes != (count+7) / 8)
513 return report_error(ERR_ILLEGAL_DATA_VALUE);
515 for (u16 i = 0; i < count; i++)
516 if (!modbus_check_coil(start + i))
517 return report_error(ERR_ILLEGAL_DATA_ADDRESS);
519 for (u16 i = 0; i < count; i++)
520 modbus_set_coil(start + i, rx_frame[i/8] & (1U << (i%8)));
526 static void func_write_multiple_registers(void)
528 if (read_remains() < 5)
529 return report_error(ERR_ILLEGAL_DATA_VALUE);
531 u16 start = read_u16();
532 u16 count = read_u16();
533 byte bytes = read_byte();
535 if (read_remains() < bytes || bytes != 2*count)
536 return report_error(ERR_ILLEGAL_DATA_VALUE);
538 for (u16 i = 0; i < count; i++)
539 if (!modbus_check_holding_register(start + i))
540 return report_error(ERR_ILLEGAL_DATA_ADDRESS);
542 for (u16 i = 0; i < count; i++)
543 modbus_set_holding_register(start + i, read_u16());
549 static void func_mask_write_register(void)
551 if (read_remains() < 6)
552 return report_error(ERR_ILLEGAL_DATA_VALUE);
554 u16 addr = read_u16();
555 u16 and_mask = read_u16();
556 u16 or_mask = read_u16();
558 if (!modbus_check_holding_register(addr))
559 return report_error(ERR_ILLEGAL_DATA_ADDRESS);
561 u16 reg = modbus_get_holding_register(addr);
562 reg = (reg & and_mask) | (or_mask & ~and_mask);
563 modbus_set_holding_register(addr, reg);
570 static void func_read_write_multiple_registers(void)
572 if (read_remains() < 9)
573 return report_error(ERR_ILLEGAL_DATA_VALUE);
575 u16 read_start = read_u16();
576 u16 read_count = read_u16();
577 u16 write_start = read_u16();
578 u16 write_count = read_u16();
579 byte write_bytes = read_byte();
581 if (read_remains() < write_bytes || write_bytes != 2*write_count)
582 return report_error(ERR_ILLEGAL_DATA_VALUE);
584 for (u16 i = 0; i < read_count; i++)
585 if (!modbus_check_holding_register(read_start + i))
586 return report_error(ERR_ILLEGAL_DATA_ADDRESS);
588 for (u16 i = 0; i < write_count; i++)
589 if (!modbus_check_holding_register(write_start + i))
590 return report_error(ERR_ILLEGAL_DATA_ADDRESS);
592 byte read_bytes = 2*write_count;
593 if (!body_fits(1 + read_bytes))
594 return report_error(ERR_ILLEGAL_DATA_VALUE);
596 for (u16 i = 0; i < write_count; i++)
597 modbus_set_holding_register(write_start + i, read_u16());
599 write_byte(read_bytes);
600 for (u16 i = 0; i < read_count; i++)
601 modbus_get_holding_register(read_start + i);
604 static void func_encapsulated_interface_transport(void)
606 if (read_remains() < 3 ||
608 return report_error(ERR_ILLEGAL_DATA_VALUE);
610 byte action = read_byte();
611 byte id = read_byte();
613 byte range_min, range_max;
616 // Streaming access to basic identification
617 range_min = MODBUS_ID_VENDOR_NAME;
618 range_max = MODBUS_ID_MAJOR_MINOR_REVISION;
621 // Streaming access to regular identification
622 range_min = MODBUS_ID_VENDOR_URL;
623 range_max = MODBUS_ID_USER_APP_NAME;
627 if (id >= MODBUS_ID_MAX || !modbus_id_strings[id])
628 return report_error(ERR_ILLEGAL_DATA_ADDRESS);
629 range_min = range_max = id;
632 return report_error(ERR_ILLEGAL_DATA_VALUE);
636 if (id < range_min || id > range_max)
640 write_byte(0x0e); // Repeat a part of the request
644 if (modbus_id_strings[MODBUS_ID_VENDOR_URL] ||
645 modbus_id_strings[MODBUS_ID_PRODUCT_NAME] ||
646 modbus_id_strings[MODBUS_ID_USER_APP_NAME])
647 write_byte(0x82); // Regular identification, both stream and individual access supported
649 write_byte(0x81); // Basic identification only
651 u16 more_follows_at = tx_size;
652 write_byte(0); // More follows: so far not
653 write_byte(0); // Next object ID: so far none
654 write_byte(0); // Number of objects
656 for (id = range_min; id <= range_max; id++) {
657 if (modbus_id_strings[id]) {
658 byte len = strlen(modbus_id_strings[id]);
659 byte remains = MODBUS_TX_BUFSIZE - 4 - tx_size; // 2 for CRC, 2 for object header
661 // If it is the only object, cut it
662 if (!tx_buf[more_follows_at + 2])
665 // More follows, report the next ID
666 tx_buf[more_follows_at] = 0xff;
667 tx_buf[more_follows_at + 1] = id;
671 tx_buf[more_follows_at + 2] ++;
674 memcpy(tx_buf + tx_size, modbus_id_strings[id], len);
680 static void process_frame(void)
682 byte func = read_byte();
684 // Prepare reply frame
685 tx_buf[0] = MODBUS_OUR_ADDRESS;
686 tx_buf[1] = rx_buf[1];
690 case FUNC_READ_COILS:
691 func_read_bits(true);
693 case FUNC_READ_DISCRETE_INPUTS:
694 func_read_bits(false);
696 case FUNC_READ_HOLDING_REGISTERS:
697 func_read_registers(true);
699 case FUNC_READ_INPUT_REGISTERS:
700 func_read_registers(false);
702 case FUNC_WRITE_SINGLE_COIL:
703 func_write_single_coil();
705 case FUNC_WRITE_SINGLE_REGISTER:
706 func_write_single_register();
708 case FUNC_WRITE_MULTIPLE_COILS:
709 func_write_multiple_coils();
711 case FUNC_WRITE_MULTIPLE_REGISTERS:
712 func_write_multiple_registers();
714 case FUNC_MASK_WRITE_REGISTER:
715 func_mask_write_register();
717 case FUNC_READ_WRITE_MULTIPLE_REGISTERS:
718 func_read_write_multiple_registers();
720 case FUNC_ENCAPSULATED_INTERFACE_TRANSPORT:
721 func_encapsulated_interface_transport();
724 report_error(ERR_ILLEGAL_FUNCTION);
727 // Finish reply frame
728 write_u16(crc16(tx_buf, tx_size));