工具 | modbus-utils(linux平台的modbus调试软件)

本文介绍了基于libmodbus库的Modbus-utils工具,包括Modbus客户端和服务器的命令行用法。通过示例展示了如何进行RTU和TCP模式的通信,如设置波特率、功能码、地址等参数,并提供了读写线圈、离散输入、保持寄存器和输入寄存器的操作。同时,文章提到了调试过程中可能遇到的问题,如端口权限问题,并给出了相应的解决办法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

modbus-utils

Modbus client and server command line tools based on libmodbus.

代码仓库

https://github.com/Krzysztow/modbus-utils

编译

for ubuntu:

sudo apt install libmodbus-dev

for buildroot:

BR2_PACKAGE_LIBMODBUS=y

编译:

$ git clone https://github.com/Krzysztow/modbus-utils
$ cd modbus-utils
$ git submodule update --init
$ mkdir build
$ cd build
$ cmake ..
$ make 

modbus协议分析

modbus协议是一种PLC协议,目的当然是为了方便主控制器与从PLC外设之间的通信。

为了避免重复编写,以下链接详细介绍了modbus rtumodbus tcp协议报文的格式,有需要请自行阅读。

modbus tcp : IoTClient开发3 - ModBusTcp协议客户端实现

modbus rtu : IoTClient开发5 - ModBusRtu协议

调试modbus_client

功能选项:

-m : rtu / tcp
-a : slave id
-r : 写入或读取的开始地址
-t : 功能码,
	(0x01) Read Coils, (0x02) Read Discrete Inputs, (0x05) Write Single Coil
	(0x03) Read Holding Registers, (0x04) Read Input Registers, (0x06) WriteSingle Register
	(0x0F) WriteMultipleCoils, (0x10) Write Multiple register
-b : 串口波特率
-d : 数据位
-s : 停止位
-p : odd 、 even 、none(奇偶校验)
-c : 读取的数目

示例命令:

./modbus_client --debug -mrtu -a1 -r1 -t0x10 -b38400 -d8 -s1 -peven /dev/ttyUSB0 0x1234 0x4321

注意点:

(1)专业词汇扫盲:

线圈寄存器:开关输出信号,读写一个寄存器的单位是1个字节,取值1或0,比如我想写入slave id为1,地址为80开始的3个线圈

$ ./modbus_client --debug -mrtu -a1 -r80 -t0x0f -b38400 -d8 -s1 -peven /dev/ttyUSB0 0x1 0x1 0x1
Data to write: 0x01 0x01 0x01 
Opening /dev/ttyUSB0 at 38400 bauds (E, 8, 1)
[01][0F][00][50][00][03][01][07][0E][99]
Waiting for a confirmation...
<01><0F><00><50><00><03><15><DB>
SUCCESS: written 3 elements!

写入线圈后,读取出来:

$ ./modbus_client --debug -mrtu -a1 -r80 -c3 -t0x01 -b38400 -d8 -s1 -peven /dev/ttyUSB0 
Opening /dev/ttyUSB0 at 38400 bauds (E, 8, 1)
[01][01][00][50][00][03][7C][1A]
Waiting for a confirmation...
<01><01><01><07><10><4A>
SUCCESS: read 3 of elements:
	Data: 0x01 0x01 0x01 

离散输入寄存器:相当于线圈寄存器的只读模式,只能读不能写

保持寄存器:可读可写,读写一个寄存器的单位是2个字节,如下是写入的命令,

$ ./modbus_client --debug -mrtu -a1 -r1 -t0x10 -b38400 -d8 -s1 -peven /dev/ttyUSB0 0x1234 0x4321
Data to write: 0x1234 0x4321 
Opening /dev/ttyUSB0 at 38400 bauds (E, 8, 1)
[01][10][00][01][00][02][04][12][34][43][21][87][FD]
Waiting for a confirmation...
<01><10><00><01><00><02><10><08>
SUCCESS: written 2 elements!

写入之后读取出来:

$ ./modbus_client --debug -mrtu -a1 -r1 -c2 -t0x03 -b38400 -d8 -s1 -peven /dev/ttyUSB0 
Opening /dev/ttyUSB0 at 38400 bauds (E, 8, 1)
[01][03][00][01][00][02][95][CB]
Waiting for a confirmation...
<01><03><04><12><34><43><21><4F><AD>
SUCCESS: read 2 of elements:
	Data: 0x1234 0x4321 

输入寄存器:相当于保持寄存器的只读模式,只能读不能写。

(2)-r选项设定地址范围为0-99,不能超过该值,如果地址超过该范围,需要在命令行指定寄存器地址范围,参数使用示例如下:

 --di 0xffff --co 0xffff --ir 0xffff --hr 0xffff

调试modbus_server

功能选项:

-m : rtu / tcp
-a : slave id

#若是rtu,有如下选项
-b : 串口波特率
-d : 数据位
-s : 停止位
-p : odd 、 even 、none(奇偶校验)

#若是tcp,有如下选项
-p:端口号

modbus_server用来模拟PLC设备

示例命令:

–di 0xffff --co 0xffff–ir 0xffff --hr 0xffff用来设定寄存器的范围

./modbus_server  --di 0xffff --co 0xffff --ir 0xffff --hr 0xffff \
-mrtu -a0x1 -b38400 -d8 -s1 -peven /dev/ttyAMA2 --debug
./modbus_server  --di 0xffff --co 0xffff --ir 0xffff --hr 0xffff \
-mtcp -a1 -p503 127.0.0.1 --debug

常见问题

Unable to listen TCP connection

在这里插入图片描述
这个问题是权限问题,参考代码:modbus-utils/libmodbus/src/modbus-tcp.c
端口号如果小于1024,运行modbus_server时,需要用root权限运行。
详细可以阅读下面代码,不做赘述。

int modbus_tcp_listen(modbus_t *ctx, int nb_connection)
{
    int new_s;
    int yes;
    struct sockaddr_in addr;
    modbus_tcp_t *ctx_tcp;

    if (ctx == NULL) {
        errno = EINVAL;
        return -1;
    }

    ctx_tcp = ctx->backend_data;

#ifdef OS_WIN32
    if (_modbus_tcp_init_win32() == -1) {
        return -1;
    }
#endif

    new_s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (new_s == -1) {
        return -1;
    }

    yes = 1;
    if (setsockopt(new_s, SOL_SOCKET, SO_REUSEADDR,
                   (char *) &yes, sizeof(yes)) == -1) {
        close(new_s);
        return -1;
    }

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
	
	//端口号小于1024的,必须以root权限运行
    /* If the modbus port is < to 1024, we need the setuid root. */
    addr.sin_port = htons(ctx_tcp->port);
    addr.sin_addr.s_addr = INADDR_ANY;
    if (bind(new_s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
        close(new_s);
        return -1;
    }

    if (listen(new_s, nb_connection) == -1) {
        close(new_s);
        return -1;
    }

    return new_s;
}

阅读代码

上述阐述如有不清晰的地方,请直接在评论区下留言,或者自行阅读代码。

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值