代码拉取完成,页面将自动刷新
TinyModbus 是一款高效、轻量级、易于移植的 Modbus 从机协议栈,使用 C 语言编写。支持 Modbus RTU 模式,TCP 模式(待开发)。支持同时创建多个实例,适用于多端口应用场景。
注:目前仅在 RT-Thread 环境下进行测试。
支持功能码
注:其它功能码暂不支持,实际产品开发中,以上功能已基本满足需求。
// 简化示例
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
如果 TinyModbus 解决了你的问题,不妨扫描上面二维码请我 喝杯咖啡~
采用 MIT 开源协议,细节请阅读项目中的 LICENSE 文件内容。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。