# TinyModbus **Repository Path**: pdenjoh/tinymodbus ## Basic Information - **Project Name**: TinyModbus - **Description**: 一个微型的 Modbus RTU 从机设备协议栈 - **Primary Language**: C - **License**: MIT - **Default Branch**: develop - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 2 - **Created**: 2022-03-20 - **Last Updated**: 2024-12-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: modbus ## README # TinyModbus ## 简介 TinyModbus 是一款高效、轻量级、易于移植的 Modbus 从机协议栈,使用 C 语言编写。支持 Modbus RTU 模式,TCP 模式(待开发)。支持同时创建多个实例,适用于多端口应用场景。 > 注:目前仅在 RT-Thread 环境下进行测试。 **支持功能码** * 01:读线圈状态 * 02:读离散输入状态 * 03:读保持寄存器 * 04:读输入寄存器 * 05:写单个线圈 * 06:写单个寄存器 * 0F:写多个线圈 * 10:写多个寄存器 * 2B:读取设备标识符 > 注:其它功能码暂不支持,实际产品开发中,以上功能已基本满足需求。 ## 实例 ```c // 简化示例 static struct modbus_s slave; static uint8_t mb_buffer[256]; static struct object_item_s basic_object_maps[] = { {OBJID_BASIC_VENDOR_NAME, "Vendor name"}, {OBJID_BASIC_PRODUCT_CODE, "A0000000001"}, {OBJID_BASIC_SOFTWARE_VERSION, "0.1"}, {OBJID_REGULAR_VENDOR_URL, "www.example.com"}, {OBJID_REGULAR_PRODUCT_NAME, "Product name"}, {OBJID_REGULAR_MODEL_NAME, "Model name"}, {OBJID_REGULAR_USER_APP_NAME, "User application nam"}, {OBJID_REGULAR_DATE, __DATE__}, {OBJID_REGULAR_HARDWARE_VERSION, "0.1"} }; static uint8_t coil[10] = {0, 1, 0, 1, 0, 0, 0, 0, 0, 0}; static uint8_t discrete_input[10] = {0, 1, 0, 1, 0, 0, 0, 0, 0, 0}; static uint16_t input_regs[10] = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90}; static uint16_t hold_regs[10] = {0, 100, 200, 300, 400, 500, 600, 700, 800, 900}; static int read_hold_regs(uint8_t *buffer, uint16_t index, uint16_t length) { LOG_D("Read holding register: %d ~ %d", 40001 + index, 40000 + index + length); rt_mutex_take(&mb_lock, RT_WAITING_FOREVER); for (int i = 0; i < length; i++) { *buffer++ = (uint8_t)(hold_regs[index + i] >> 8); *buffer++ = (uint8_t)(hold_regs[index + i] & 0xFF); } rt_mutex_release(&mb_lock); return MB_EX_NONE; } static int write_hold_regs(const uint8_t *buffer, uint16_t index, uint16_t length) { LOG_D("Write holding register: %d ~ %d", 40001 + index, 40000 + index + length); // 1. 拷贝数据至缓存 // 2. 校验数据 rt_mutex_take(&mb_lock, RT_WAITING_FOREVER); for (int i = 0; i < length; i++) { hold_regs[index + i] = *buffer++ << 8; hold_regs[index + i] |= *buffer++; } rt_mutex_release(&mb_lock); return MB_EX_NONE; } static struct modbus_slave_util_s hold_util = {0, sizeof(hold_regs), &read_hold_regs, &write_hold_regs}; int main(void) { /* 初始化 Modbus slave */ mb_slave_init(&slave, MB_BACKEND_TYPE_RTU); mb_slave_set_addr(&slave, 1); mb_slave_set_dev_info(&slave, &basic_object_maps[0], sizeof(basic_object_maps) / sizeof(struct object_item_s)); /* 注册寄存器回调函数 */ mb_slave_set_util(&slave, MB_REG_TYPE_COIL, &coil_util); mb_slave_set_util(&slave, MB_REG_TYPE_DISCRETE_INPUTS, &discrete_input_util); mb_slave_set_util(&slave, MB_REG_TYPE_INPUT_REGS, &input_util); mb_slave_set_util(&slave, MB_REG_TYPE_HOLD_REGS, &hold_util); for (;;) { uint16_t len = serial_receive(serial, mb_buffer, sizeof(mb_buffer), 20); len = mb_slave_handle(&slave, mb_buffer, len); if (len > 0) { serial_transfer(serial, mb_buffer, len); } } } ``` ## 资源占用 **开发环境 MDK 5.37.0** ``` Code (inc. data) RO Data RW Data ZI Data Debug Object Name 1356 308 120 184 360 12486 modbus_rtu_slave.o 56 8 512 0 0 1207 mb_crc.o 108 0 0 20 0 5185 mb_rtu.o 2022 292 72 0 0 13359 tinymodbus.o ``` ## 贡献 ## 支持 ![support](docs/wechat_support.png) 如果 TinyModbus 解决了你的问题,不妨扫描上面二维码请我 **喝杯咖啡~** ## 许可 采用 MIT 开源协议,细节请阅读项目中的 LICENSE 文件内容。