From c226721f5fe0cb0499f75787f7794abe3cfcbe84 Mon Sep 17 00:00:00 2001 From: zhaohe Date: Fri, 2 Feb 2024 23:10:09 +0800 Subject: [PATCH] update --- components/api/zi_uart_sender.hpp | 15 ++ components/modbus/modbus_basic.hpp | 126 +++++++++++++++ components/modbus/modbus_client.cpp | 90 +++++++++++ components/modbus/modbus_client.hpp | 44 ++++++ components/modbus/modbus_processer.cpp | 280 +++++++++++++++++++++++++++++++++ components/modbus/modbus_processer.hpp | 43 +++++ 6 files changed, 598 insertions(+) create mode 100644 components/api/zi_uart_sender.hpp create mode 100644 components/modbus/modbus_client.cpp create mode 100644 components/modbus/modbus_client.hpp create mode 100644 components/modbus/modbus_processer.cpp create mode 100644 components/modbus/modbus_processer.hpp diff --git a/components/api/zi_uart_sender.hpp b/components/api/zi_uart_sender.hpp new file mode 100644 index 0000000..f6dc264 --- /dev/null +++ b/components/api/zi_uart_sender.hpp @@ -0,0 +1,15 @@ +#pragma once +#include + +#include + +#include "sdk\components\zprotocols\zcancmder_v2\api\errorcode.hpp" + +namespace iflytop { +using namespace std; +class ZIUartSender { + public: + virtual ~ZIUartSender() {} + virtual void send(const uint8_t *data, size_t len) = 0; +}; +} // namespace iflytop \ No newline at end of file diff --git a/components/modbus/modbus_basic.hpp b/components/modbus/modbus_basic.hpp index 06498f7..0efa764 100644 --- a/components/modbus/modbus_basic.hpp +++ b/components/modbus/modbus_basic.hpp @@ -1,7 +1,133 @@ #pragma once #include #include +/** + * @brief + * + * dep: + * basic_type.h + * + * + * TODO: + * 目前测试通过的功能码 + * 0x04 + * 0x10 + * + */ + +/*定义Modbus的操作功能码,支持01、02、03、04、05、06、15、16功能码*/ +typedef enum { + // ReadCoilStatus 读线圈状态(读多个输出位的状态) + ModbusOrder01 = 0x01, + // ReadInputStatus 读输入位状态(读多个输入位的状态) + ModbusOrder02 = 0x02, + // ReadHoldingRegister 读保持寄存器(读多个保持寄存器的数值) + ModbusOrder03 = 0x03, + // ReadInputRegister 读输入寄存器(读多个输入寄存器的数值) + ModbusOrder04 = 0x04, + // WriteSingleCoil 强制单个线圈(强制单个输出位的状态) + ModbusOrder05 = 0x05, + // WriteSingleRegister 预制单个寄存器(设定一个寄存器的数值) + ModbusOrder06 = 0x06, + // WriteMultipleCoil 强制多个线圈(强制多个输出位的状态) + ModbusOrder0F = 0x0F, + // WriteMultipleRegister 预制多个寄存器(设定多个寄存器的数值) + ModbusOrder10 = 0x10, + // ReadFileRecord 读文件记录 + ModbusOrder14 = 0x14, + // WriteFileRecord 写文件记录 + ModbusOrder15 = 0x15, + // MaskWriteRegister 屏蔽写寄存器 + ModbusOrder16 = 0x16, + // ReadWriteMultiRegister 读写多个寄存器 + ModbusOrder17 = 0x17, + // ReadDeviceID读设备识别码 + ModbusOrder2B = 0x2B, +} ModbusFunctionCode; + +/*定义接收到指令检测错误时的错误码*/ +typedef enum { + Modbus_OK = 0x00, + InvalidFunctionCode = 0x01, // 不合法功能代码 + IllegalDataAddress = 0x02, // 非法的数据地址 + IllegalDataValues = 0x03, // 非法的数据值或者范围 + SlaveFailure = 0x04, // 从站设备故障 + Acknowledgement = 0x05, // 确认 + SlaveDeviceBusy = 0x06, // 从属设备忙 + MemoryParityError = 0x08, // 存储奇偶性差错 + GatewayDisabled = 0x0A, // 不可用网关路径 + GatewayResponseFailed = 0x0B // 网关目标设备响应失败 +} ModbusStatus; + +typedef struct { + uint8_t deviceid; + ModbusFunctionCode functionCode; + union { + /**********read************/ + struct { + uint16_t startbit; // bit + uint16_t numbit; // bit + } O01; // ReadCoilStatus + struct { + uint16_t startbit; // bit + uint16_t numbit; // bit + } O02; // ReadInputStatus + struct { + uint16_t startreg; // byte + uint16_t numreg; // reg(一个reg==16bit) + } O03; // ReadInputStatus + struct { + uint16_t startreg; // byte + uint16_t numreg; // reg(一个reg==16bit) + } O04; // ReadInputStatus + /**********write************/ + struct { + uint16_t startbit; // bit + uint16_t numbit; // bit + uint8_t bytenum; + uint8_t *bit; + } O0F; // WriteMultipleCoil + struct { + uint16_t startreg; // byte + uint16_t numreg; // byte + uint8_t bytenum; // numreg*2 + uint8_t *reg; + } O10; // WriteMultipleCoil + } d; +} ModbusMasterData_t; +typedef struct { + ModbusFunctionCode functionCode; + uint8_t deviceId; + union { + /**********read_receipt************/ + struct { + uint8_t bytenum; // bit + uint8_t *byte_table; + } O01; // ReadCoilStatus + struct { + uint8_t bytenum; // byte_table + uint8_t *byte_table; + } O02; // ReadInputStatus + struct { + uint8_t bytenum; // byte + uint8_t *reg; + } O03; // ReadInputStatus + struct { + uint8_t bytenum; // byte + uint8_t *reg; + } O04; // ReadInputStatus + /**********write_receipt************/ + struct { + uint16_t startbit; + uint16_t bitnum; // bit + } O0F; // WriteMultipleCoil-->对应01 + struct { + uint16_t startreg; + uint16_t regnum; // byte + } O10; // --->对应03 + } d; +} ModbusSlaveData_t; /** * @brief 生成CRC16校验码 * diff --git a/components/modbus/modbus_client.cpp b/components/modbus/modbus_client.cpp new file mode 100644 index 0000000..6a62969 --- /dev/null +++ b/components/modbus/modbus_client.cpp @@ -0,0 +1,90 @@ +#include "modbus_client.hpp" + +#include + +#include "modbus_basic.hpp" +#include "sdk\os\delay.hpp" +using namespace iflytop; + +static uint8_t modbus_rx_buf[256]; +static uint8_t modbus_tx_buf[256]; +static bool modbus_rx_is_ready = false; +static int modbus_rx_size = 256; + +static void modbux_tx(uint8_t* rx, uint16_t len) { ModulebusClient::Inst()->sendpacket(rx, len); } +static void modbux_process_rx(modbus_processer_context_t* context) { ModulebusClient::Inst()->process_rx_packet(context); } + +void ModulebusClient::init(ZIUartReceiver* receiver, ZIUartSender* sender, int deviceId, // + on_reg_read_t regreadcb, // + on_reg_write_t regwritecb) { + static modbus_processer_t s_modbus_processer = {}; + s_modbus_processer.modbus_device_id = deviceId; + s_modbus_processer.modbus_processer_rx_buf = modbus_rx_buf; + s_modbus_processer.modbus_processer_rx_buf_size = sizeof(modbus_rx_buf); + s_modbus_processer.modbus_processer_tx_buf = modbus_tx_buf; + s_modbus_processer.modbus_processer_tx_buf_size = sizeof(modbus_tx_buf); + s_modbus_processer.tx = modbux_tx; + s_modbus_processer.process_rx = modbux_process_rx; + + m_receiver = receiver; + m_sender = sender; + m_deviceId = deviceId; + + m_regreadcb = regreadcb; + m_regwritecb = regwritecb; + modbus_processer_init(&s_modbus_processer); + + receiver->startRx([this](uint8_t* data, size_t len) { // + if (modbus_rx_is_ready) return; + if (len > 256) return; + memcpy(modbus_rx_buf, data, len); + modbus_rx_size = len; + modbus_rx_is_ready = true; + }); +} +void ModulebusClient::loop() { + if (modbus_rx_is_ready) { + modbus_processer_process_data(modbus_rx_buf, modbus_rx_size); + modbus_rx_is_ready = false; + } +} +void ModulebusClient::sendpacket(uint8_t* data, uint16_t len) { m_sender->send(data, len); } + +void ModulebusClient::process_rx_packet(modbus_processer_context_t* context) { + ModbusFunctionCode fcode = modbus_get_function_code(context); + if (fcode == ModbusOrder10) { + /** + * @brief 基本GPIO写 + */ + + uint16_t startreg = context->rx->d.O10.startreg; + uint16_t endreg = context->rx->d.O10.startreg + context->rx->d.O10.numreg; + uint16_t regnum = context->rx->d.O10.numreg; + for (int i = 0; i < regnum; i++) { + int32_t regoff = i + startreg; + if (m_regwritecb) { + m_regwritecb(regoff, modbus_get_reg_10(context, regoff)); + } + } + + } else if (fcode == ModbusOrder03) { + uint16_t startreg = context->rx->d.O03.startreg; + uint16_t endreg = context->rx->d.O03.startreg + context->rx->d.O03.numreg; + uint16_t regnum = context->rx->d.O03.numreg; + + for (int i = 0; i < regnum; i++) { + int32_t regoff = i + startreg; + uint16_t regval = 0; + if (m_regreadcb) { + m_regreadcb(regoff, regval); + } + modbus_set_tx_reg_03(context, regoff, regval); + } + } + + if (fcode == ModbusOrder10) { + modbus_send_10(context, Modbus_OK); + } else if (fcode == ModbusOrder03) { + modbus_send_03(context, Modbus_OK); + } +} diff --git a/components/modbus/modbus_client.hpp b/components/modbus/modbus_client.hpp new file mode 100644 index 0000000..5303aa6 --- /dev/null +++ b/components/modbus/modbus_client.hpp @@ -0,0 +1,44 @@ +#pragma once +#include "modbus_processer.hpp" +#include "sdk/os/zos.hpp" +#include "sdk\components\api\zi_uart_sender.hpp" +#include "sdk\components\cmdscheduler\cmd_scheduler_v2.hpp" +#include "sdk\components\hardware\uart\zuart_dma_receiver.hpp" +#include "sdk\components\zcancmder\zcan_board_module.hpp" +#include "sdk\components\zcancmder\zcanreceiver.hpp" +#include "sdk\components\zprotocol_helper\micro_computer_module_device_script_cmder_paser.hpp" +#include "sdk\components\zprotocols\zcancmder_v2\protocol_event_bus_sender.hpp" +#include "sdk\components\zprotocols\zcancmder_v2\protocol_parser.hpp" +#include "sdk\components\zprotocols\zcancmder_v2\zmodule_device_manager.hpp" + +namespace iflytop { + +typedef function on_reg_read_t; +typedef function on_reg_write_t; + +class ModulebusClient { + ZIUartReceiver* m_receiver; + ZIUartSender* m_sender; + int m_deviceId; + on_reg_read_t m_regreadcb; + on_reg_write_t m_regwritecb; + + ModulebusClient() {} + + public: + static ModulebusClient* Inst() { + static ModulebusClient instance; + return &instance; + } + + void init(ZIUartReceiver* receiver, ZIUartSender* sender, int deviceId, // + on_reg_read_t regreadcb, // + on_reg_write_t regwritecb); + void loop(); + + public: + void process_rx_packet(modbus_processer_context_t* context); + void sendpacket(uint8_t* data, uint16_t len); +}; + +} // namespace iflytop \ No newline at end of file diff --git a/components/modbus/modbus_processer.cpp b/components/modbus/modbus_processer.cpp new file mode 100644 index 0000000..01cf33c --- /dev/null +++ b/components/modbus/modbus_processer.cpp @@ -0,0 +1,280 @@ +#include "modbus_processer.hpp" + +#include +#include + +/***********************485rx**************************/ +// 接收到了多少数据 +// volatile uint16_t s_modbus_uart_rx_off = 0; +// 当前是否正在处理接收到的数据 +// volatile bool s_modbus_uart_rx_buf_is_processing = false; +/***********************485tx**************************/ +static modbus_processer_t* g_processer; + +#define GET_UINT16(uint8) (uint16_t)(((uint16_t)((uint8)[0]) << 8) + (uint8)[1]) +void modbus_processer_process_data(uint8_t* rx, uint16_t len); +void modbus_processer_init(modbus_processer_t* processer) { g_processer = processer; } + +void ModbusProcessRxData(uint8_t* rxraw, uint8_t length, ModbusMasterData_t* rxparsed) { + rxparsed->functionCode = (ModbusFunctionCode)rxraw[1]; + if (rxraw[1] == ModbusOrder01 || rxraw[1] == ModbusOrder02 || rxraw[1] == ModbusOrder03 || rxraw[1] == ModbusOrder04) { + /** + * @brief + * 由于是共用体,所以均给001赋值即可 + */ + rxparsed->d.O01.startbit = rxraw[2] * 256 + rxraw[3]; + rxparsed->d.O01.numbit = rxraw[4] * 256 + rxraw[5]; + } else if (rxraw[1] == ModbusOrder0F || rxraw[1] == ModbusOrder10) { + /** + * @brief + * 由于是共用体,所以均给0F赋值即可 + */ + rxparsed->d.O0F.startbit = rxraw[2] * 256 + rxraw[3]; + rxparsed->d.O0F.numbit = rxraw[4] * 256 + rxraw[5]; + rxparsed->d.O0F.bytenum = rxraw[6]; + rxparsed->d.O0F.bit = &rxraw[7]; + } else { + /** + * @brief Not support now + */ + } +} + +#define UINT16ToUINT8(u16d, u8addbegin) \ + { \ + (u8addbegin)[0] = u16d >> 8; \ + (u8addbegin)[1] = (uint8_t)u16d; \ + } + +void ModbusCreateTx_setReg(uint8_t* txbuffer, uint8_t length, uint16_t off, uint16_t regdata) { + if (3 + off * 2 > length - 2) { + return; + } + txbuffer[3 + off * 2] = regdata >> 8; + txbuffer[3 + off * 2 + 1] = (uint8_t)regdata; +} + +void ModbusCreateTxData(uint8_t* txbuffer, uint8_t length, uint16_t* sendlength, ModbusSlaveData_t* txdata) { + /** + * @brief TODO:添加txbuffer长度计算 + */ + if (length < 4) return; + txbuffer[0] = txdata->deviceId; + txbuffer[1] = (uint8_t)txdata->functionCode; + *sendlength = 0; + volatile uint16_t _sendlength = 0; + volatile uint16_t i = 0; + + if (txdata->functionCode == ModbusOrder01 || txdata->functionCode == ModbusOrder02 || txdata->functionCode == ModbusOrder03 || txdata->functionCode == ModbusOrder04) { + /** + * @brief 01,02 指令操作bit + */ + + // 读取多个输出状态 + // sendLen = + // add(1byte)+functionCode(1byte)+addNum(1)+crc(2) = 5+numbyte + volatile uint16_t numbyte = txdata->d.O01.bytenum; + _sendlength = 5 + numbyte; + if (length < _sendlength) return; + txbuffer[2] = txdata->d.O01.bytenum; + if (txdata->d.O01.byte_table != nullptr) { + for (i = 0; i < numbyte; i++) { + txbuffer[3 + i] = txdata->d.O01.byte_table[i]; + } + } + } else if (txdata->functionCode == ModbusOrder0F || txdata->functionCode == ModbusOrder10) { + // 写入多个输出 + // sendLen = add(1byte)+functionCode(1byte)+startAdd(2)+addNum(2)+crc(2) = 8 + _sendlength = 8; + if (length < _sendlength) return; + + UINT16ToUINT8(txdata->d.O0F.startbit, &txbuffer[2]); + UINT16ToUINT8(txdata->d.O0F.bitnum, &txbuffer[4]); + } else { + /** + * @brief Not support now + */ + } + // calculate crc + if (_sendlength > 2) { + modbus_pack_crc_to_packet(txbuffer, _sendlength); + } + *sendlength = _sendlength; +} + +void ModbusCreateExceptionData(uint8_t* txbuffer, uint8_t length, uint16_t* sendlength, uint8_t deviceid, uint8_t functioncode, ModbusStatus status) { + /** + * @brief TODO:添加txbuffer长度计算 + */ + volatile uint16_t _sendlength = 0; + volatile uint16_t i = 0; + + if (length < 4) return; + txbuffer[0] = deviceid; + txbuffer[1] = functioncode | 0x80; + txbuffer[2] = (uint8_t)status; + *sendlength = 0; + // sendLen = add(1byte)+functionCode(1byte)+exception(1)+crc(2) = 4 + _sendlength = 4; + modbus_pack_crc_to_packet(txbuffer, _sendlength); + *sendlength = _sendlength; + return; +} +#if 0 +void modbus_processer_try_process_data(void) { + /** + * @brief + * 根据modbus协议,当超过3.5个字符时间后依然没有收到数据 + */ + // bool receive_one_packet = false; // 因为keil报警告才注释 + if (s_modbus_uart_rx_off != 0) { + uint16_t modbus_uart_rx_off_before = s_modbus_uart_rx_off; + + g_processer->port_delay_us(g_processer->modbus_baundrate_one_packet_delay_us); + + g_processer->port_enter_critical(); + if (s_modbus_uart_rx_off == modbus_uart_rx_off_before) { + s_modbus_uart_rx_buf_is_processing = true; + } + g_processer->port_exit_critical(); + + if (s_modbus_uart_rx_buf_is_processing) { + modbus_processer_process_data(g_processer->modbus_processer_rx_buf, s_modbus_uart_rx_off); + g_processer->port_enter_critical(); + s_modbus_uart_rx_off = 0; + s_modbus_uart_rx_buf_is_processing = false; + g_processer->port_exit_critical(); + } + } +} +#endif + +/*********************************************************************************************************************** + * ==================================================modbus消息处理=================================================== * + ***********************************************************************************************************************/ + void modbus_processer_process_data(uint8_t* rx, uint16_t rxlen) { + /** + * @brief modbus接收完成以后在这里进行处理数据 + * + */ + // 如果不是广播信息或者不是当前设备的信息,丢弃 + if (rx[0] != 0 && rx[0] != g_processer->modbus_device_id) { + return; + } + // CRC校验失败 + if (!modbus_checkcrc16(rx, rxlen)) { + return; + } + // if(functioncode) + static ModbusMasterData_t rxorder; + static ModbusSlaveData_t txorder; + // 将接受到的数据进行组包 + ModbusProcessRxData(rx, rxlen, &rxorder); + // static uint16_t txsendlen = 0; // 因为keil报警告才注释 + txorder.deviceId = g_processer->modbus_device_id; + // 功能码 + txorder.functionCode = rxorder.functionCode; + + modbus_processer_context_t context = {0}; + context.tx = &txorder; + context.rx = &rxorder; + g_processer->process_rx(&context); +} + +/*********************************************************************************************************************** + * ======================================================Extern======================================================= * + ***********************************************************************************************************************/ + +ModbusFunctionCode modbus_get_function_code(modbus_processer_context_t* context) { // + return context->tx->functionCode; +} +void modbus_set_tx_reg_03(modbus_processer_context_t* context, uint16_t regoff, uint16_t regdata) { + uint16_t off = regoff - context->rx->d.O03.startreg; + ModbusCreateTx_setReg(g_processer->modbus_processer_tx_buf, g_processer->modbus_processer_tx_buf_size, off, // + regdata); +} +void modbus_set_tx_regs_03(modbus_processer_context_t* context, uint16_t regoff, uint16_t* regdata, int reglen) { + for (int i = 0; i < reglen; i++) { + modbus_set_tx_reg_03(context, regoff + i, regdata[i]); + } +} + +uint16_t modbus_get_reg_10(modbus_processer_context_t* context, uint16_t regoff) { + uint16_t off = regoff - context->rx->d.O10.startreg; + uint8_t* data = context->rx->d.O10.reg; + if ((off + 1) * 2 <= context->rx->d.O10.bytenum) { + uint16_t u16 = GET_UINT16(&data[off * 2]); + return u16; + } else { + uint16_t u16 = data[off * 2]; + return u16; + } +} +uint8_t* modbus_get_buf_10(modbus_processer_context_t* context, uint16_t regoff) { + uint16_t off = regoff - context->rx->d.O10.startreg; + uint8_t* data = context->rx->d.O10.reg; + return &data[off * 2]; +} +bool modbus_if_register_exists_03(modbus_processer_context_t* context, uint16_t regoff) { + uint16_t startreg = context->rx->d.O03.startreg; + uint16_t endreg = context->rx->d.O03.startreg + context->rx->d.O03.numreg; + return regoff >= startreg && regoff < endreg; +} +bool modbus_if_registers_exists_03(modbus_processer_context_t* context, uint16_t regoff, uint16_t regnum) { return (modbus_if_register_exists_03(context, regoff) && modbus_if_register_exists_03(context, regoff + regnum - 1)); } + +bool modbus_if_register_exists_10(modbus_processer_context_t* context, uint16_t regoff) { + uint16_t startreg = context->rx->d.O10.startreg; + uint16_t endreg = context->rx->d.O10.startreg + context->rx->d.O10.numreg; + return regoff >= startreg && regoff < endreg; +} +void modbus_send_03(modbus_processer_context_t* context, ModbusStatus modbus_status) { + uint16_t sendlegth = 0; + if (modbus_status == Modbus_OK) { + /** + * @brief 正常 + */ + context->tx->functionCode = context->rx->functionCode; + context->tx->deviceId = g_processer->modbus_device_id; + context->tx->d.O03.bytenum = context->rx->d.O03.numreg * 2; + context->tx->d.O03.reg = nullptr; + // 组成响应包 + ModbusCreateTxData(g_processer->modbus_processer_tx_buf, g_processer->modbus_processer_tx_buf_size, &sendlegth, context->tx); + // 包组成以后发送给服务端 + g_processer->tx(g_processer->modbus_processer_tx_buf, sendlegth); + } else { + // LOGD("error"); + /** + * @brief 异常 + */ + // 处理异常情况 + ModbusCreateExceptionData(g_processer->modbus_processer_tx_buf, // + g_processer->modbus_processer_tx_buf_size, // + &sendlegth, // + g_processer->modbus_device_id, // + context->rx->functionCode, // + modbus_status); + // 组包完成发送应答 + g_processer->tx(g_processer->modbus_processer_tx_buf, sendlegth); + } +} +void modbus_send_10(modbus_processer_context_t* context, ModbusStatus modbus_status) { + uint16_t sendlegth = 0; + if (modbus_status == Modbus_OK) { + context->tx->functionCode = context->rx->functionCode; + context->tx->deviceId = g_processer->modbus_device_id; + context->tx->d.O10.regnum = context->rx->d.O10.numreg; + context->tx->d.O10.startreg = context->rx->d.O10.startreg; + // 构造回执,并发送 + ModbusCreateTxData(g_processer->modbus_processer_tx_buf, g_processer->modbus_processer_tx_buf_size, &sendlegth, context->tx); + g_processer->tx(g_processer->modbus_processer_tx_buf, sendlegth); + } else { + // 构造异常包并发送 + ModbusCreateExceptionData(g_processer->modbus_processer_tx_buf, // + g_processer->modbus_processer_tx_buf_size, // + &sendlegth, // + g_processer->modbus_device_id, // + context->rx->functionCode, // + modbus_status); + g_processer->tx(g_processer->modbus_processer_tx_buf, sendlegth); + } +} diff --git a/components/modbus/modbus_processer.hpp b/components/modbus/modbus_processer.hpp new file mode 100644 index 0000000..1a7b51f --- /dev/null +++ b/components/modbus/modbus_processer.hpp @@ -0,0 +1,43 @@ +#pragma once +#include + +#include "modbus_basic.hpp" + +typedef struct { + ModbusMasterData_t* rx; + ModbusSlaveData_t* tx; +} modbus_processer_context_t; + +typedef struct modbus_processer { + uint8_t modbus_device_id; // default 0x01; + + uint8_t* modbus_processer_rx_buf; + int modbus_processer_rx_buf_size; // + + uint8_t* modbus_processer_tx_buf; + int modbus_processer_tx_buf_size; // + + /*************************************/ + void (*tx)(uint8_t* rx, uint16_t len); + void (*process_rx)(modbus_processer_context_t* context); +} modbus_processer_t; + +void modbus_processer_init(modbus_processer_t* processer); +void modbus_processer_push_data(uint8_t rxdata); +// void modbus_processer_try_process_data(void); +void modbus_processer_process_data(uint8_t* rx, uint16_t rxlen); + +/*********************************************************************************************************************** + * ====================================================辅助方法==================================================== * + ***********************************************************************************************************************/ +ModbusFunctionCode modbus_get_function_code(modbus_processer_context_t* context); + +void modbus_set_tx_reg_03(modbus_processer_context_t* context, uint16_t regoff, uint16_t regdata); +void modbus_set_tx_regs_03(modbus_processer_context_t* context, uint16_t regoff, uint16_t* regdata, int reglen); +uint16_t modbus_get_reg_10(modbus_processer_context_t* context, uint16_t regoff); +bool modbus_if_register_exists_03(modbus_processer_context_t* context, uint16_t regoff); +bool modbus_if_registers_exists_03(modbus_processer_context_t* context, uint16_t regoff, uint16_t reglen); +bool modbus_if_register_exists_10(modbus_processer_context_t* context, uint16_t regoff); +uint8_t* modbus_get_buf_10(modbus_processer_context_t* context, uint16_t regoff); +void modbus_send_03(modbus_processer_context_t* context, ModbusStatus modbus_status); +void modbus_send_10(modbus_processer_context_t* context, ModbusStatus modbus_status);