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);
483 static void func_write_single_register(void)
485 if (read_remains() < 4)
486 return report_error(ERR_ILLEGAL_DATA_VALUE);
488 u16 addr = read_u16();
489 u16 value = read_u16();
491 if (!modbus_check_holding_register(addr))
492 return report_error(ERR_ILLEGAL_DATA_ADDRESS);
494 modbus_set_holding_register(addr, value);
497 static void func_write_multiple_coils(void)
499 if (read_remains() < 5)
500 return report_error(ERR_ILLEGAL_DATA_VALUE);
502 u16 start = read_u16();
503 u16 count = read_u16();
504 byte bytes = read_byte();
506 if (read_remains() < bytes || bytes != (count+7) / 8)
507 return report_error(ERR_ILLEGAL_DATA_VALUE);
509 for (u16 i = 0; i < count; i++)
510 if (!modbus_check_coil(start + i))
511 return report_error(ERR_ILLEGAL_DATA_ADDRESS);
513 for (u16 i = 0; i < count; i++)
514 modbus_set_coil(start + i, rx_frame[i/8] & (1U << (i%8)));
517 static void func_write_multiple_registers(void)
519 if (read_remains() < 5)
520 return report_error(ERR_ILLEGAL_DATA_VALUE);
522 u16 start = read_u16();
523 u16 count = read_u16();
524 byte bytes = read_byte();
526 if (read_remains() < bytes || bytes != 2*count)
527 return report_error(ERR_ILLEGAL_DATA_VALUE);
529 for (u16 i = 0; i < count; i++)
530 if (!modbus_check_holding_register(start + i))
531 return report_error(ERR_ILLEGAL_DATA_ADDRESS);
533 for (u16 i = 0; i < count; i++)
534 modbus_set_holding_register(start + i, read_u16());
537 static void func_mask_write_register(void)
539 if (read_remains() < 6)
540 return report_error(ERR_ILLEGAL_DATA_VALUE);
542 u16 addr = read_u16();
543 u16 and_mask = read_u16();
544 u16 or_mask = read_u16();
546 if (!modbus_check_holding_register(addr))
547 return report_error(ERR_ILLEGAL_DATA_ADDRESS);
549 u16 reg = modbus_get_holding_register(addr);
550 reg = (reg & and_mask) | (or_mask & ~and_mask);
551 modbus_set_holding_register(addr, reg);
554 static void func_read_write_multiple_registers(void)
556 if (read_remains() < 9)
557 return report_error(ERR_ILLEGAL_DATA_VALUE);
559 u16 read_start = read_u16();
560 u16 read_count = read_u16();
561 u16 write_start = read_u16();
562 u16 write_count = read_u16();
563 byte write_bytes = read_byte();
565 if (read_remains() < write_bytes || write_bytes != 2*write_count)
566 return report_error(ERR_ILLEGAL_DATA_VALUE);
568 for (u16 i = 0; i < read_count; i++)
569 if (!modbus_check_holding_register(read_start + i))
570 return report_error(ERR_ILLEGAL_DATA_ADDRESS);
572 for (u16 i = 0; i < write_count; i++)
573 if (!modbus_check_holding_register(write_start + i))
574 return report_error(ERR_ILLEGAL_DATA_ADDRESS);
576 byte read_bytes = 2*write_count;
577 if (!body_fits(1 + read_bytes))
578 return report_error(ERR_ILLEGAL_DATA_VALUE);
580 for (u16 i = 0; i < write_count; i++)
581 modbus_set_holding_register(write_start + i, read_u16());
583 write_byte(read_bytes);
584 for (u16 i = 0; i < read_count; i++)
585 modbus_get_holding_register(read_start + i);
588 static void func_encapsulated_interface_transport(void)
590 if (read_remains() < 3 ||
592 return report_error(ERR_ILLEGAL_DATA_VALUE);
594 byte action = read_byte();
595 byte id = read_byte();
597 byte range_min, range_max;
600 // Streaming access to basic identification
601 range_min = MODBUS_ID_VENDOR_NAME;
602 range_max = MODBUS_ID_MAJOR_MINOR_REVISION;
605 // Streaming access to regular identification
606 range_min = MODBUS_ID_VENDOR_URL;
607 range_max = MODBUS_ID_USER_APP_NAME;
611 if (id >= MODBUS_ID_MAX || !modbus_id_strings[id])
612 return report_error(ERR_ILLEGAL_DATA_ADDRESS);
613 range_min = range_max = id;
616 return report_error(ERR_ILLEGAL_DATA_VALUE);
620 if (id < range_min || id > range_max)
624 write_byte(0x0e); // Repeat a part of the request
628 if (modbus_id_strings[MODBUS_ID_VENDOR_URL] ||
629 modbus_id_strings[MODBUS_ID_PRODUCT_NAME] ||
630 modbus_id_strings[MODBUS_ID_USER_APP_NAME])
631 write_byte(0x82); // Regular identification, both stream and individual access supported
633 write_byte(0x81); // Basic identification only
635 u16 more_follows_at = tx_size;
636 write_byte(0); // More follows: so far not
637 write_byte(0); // Next object ID: so far none
638 write_byte(0); // Number of objects
640 for (id = range_min; id <= range_max; id++) {
641 if (modbus_id_strings[id]) {
642 byte len = strlen(modbus_id_strings[id]);
643 byte remains = MODBUS_TX_BUFSIZE - 4 - tx_size; // 2 for CRC, 2 for object header
645 // If it is the only object, cut it
646 if (!tx_buf[more_follows_at + 2])
649 // More follows, report the next ID
650 tx_buf[more_follows_at] = 0xff;
651 tx_buf[more_follows_at + 1] = id;
655 tx_buf[more_follows_at + 2] ++;
658 memcpy(tx_buf + tx_size, modbus_id_strings[id], len);
664 static void process_frame(void)
666 byte func = read_byte();
668 // Prepare reply frame
669 tx_buf[0] = MODBUS_OUR_ADDRESS;
670 tx_buf[1] = rx_buf[1];
674 case FUNC_READ_COILS:
675 func_read_bits(true);
677 case FUNC_READ_DISCRETE_INPUTS:
678 func_read_bits(false);
680 case FUNC_READ_HOLDING_REGISTERS:
681 func_read_registers(true);
683 case FUNC_READ_INPUT_REGISTERS:
684 func_read_registers(false);
686 case FUNC_WRITE_SINGLE_COIL:
687 func_write_single_coil();
689 case FUNC_WRITE_SINGLE_REGISTER:
690 func_write_single_register();
692 case FUNC_WRITE_MULTIPLE_COILS:
693 func_write_multiple_coils();
695 case FUNC_WRITE_MULTIPLE_REGISTERS:
696 func_write_multiple_registers();
698 case FUNC_MASK_WRITE_REGISTER:
699 func_mask_write_register();
701 case FUNC_READ_WRITE_MULTIPLE_REGISTERS:
702 func_read_write_multiple_registers();
704 case FUNC_ENCAPSULATED_INTERFACE_TRANSPORT:
705 func_encapsulated_interface_transport();
708 report_error(ERR_ILLEGAL_FUNCTION);
711 // Finish reply frame
712 write_u16(crc16(tx_buf, tx_size));