Hopi-pico/modbus_rtu.h

51 lines
1.7 KiB
C

#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
// Simple Modbus RTU master focused on function 0x03 (Read Holding Registers).
// Transport is byte-stream oriented (USB-serial in this project).
typedef struct {
uint8_t slave_id;
bool disable_crc;
} modbus_rtu_master_config_t;
typedef struct {
modbus_rtu_master_config_t cfg;
// RX accumulation
uint8_t rx_buf[256];
size_t rx_len;
// Pending request tracking
bool awaiting_response;
uint32_t request_started_ms;
uint16_t expected_byte_count;
} modbus_rtu_master_t;
void modbus_rtu_master_init(modbus_rtu_master_t *m, modbus_rtu_master_config_t cfg);
// Builds a Read Holding Registers (0x03) request.
// Returns frame length.
size_t modbus_rtu_build_read_holding(uint8_t *out, size_t out_cap,
uint8_t slave_id, uint16_t start_addr, uint16_t quantity,
bool disable_crc);
// Feed received bytes into the Modbus parser.
void modbus_rtu_feed(modbus_rtu_master_t *m, const uint8_t *data, size_t len);
// Returns true when a full response for function 0x03 is present in rx_buf.
// If true, `*out_data_offset` points to first data byte, `*out_word_count` is number of 16-bit registers.
bool modbus_rtu_try_parse_read_holding_response(modbus_rtu_master_t *m,
uint8_t expected_slave_id,
uint16_t expected_quantity,
size_t *out_data_offset,
uint16_t *out_word_count);
uint16_t modbus_rtu_get_u16_be(const uint8_t *p);
uint16_t modbus_rtu_crc16(const uint8_t *data, size_t len);
float modbus_float_dcba(uint16_t w1, uint16_t w2);