Win10编译和测试libModbus

本文介绍了在项目中选择合适的Modbus协议栈的过程,并详细记录了使用libModbus进行编译、配置及测试的步骤。包括搭建开发环境、解决常见错误、实现RTU与TCP模式下的读取操作。

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

前题

项目需要使用到 Modbus 协议,不想自己写一个协议栈,虽然 Modbus 协议比较简单。

可用的 Modbus 协议栈

libModubs

开源代码。官网地址为:https://libmodbus.org

freeModubs

开源代码。官网地址为:https://www.embedded-solutions.at/en/freemodbus/。可以从 github 中下载,https://github.com/cwalter-at/freemodbus

emModubs

segger 公司的。商业代码。不出钱是没法用的。https://www.segger.com/downloads/emmodbus/

个人选择

emModbus,商业代码。穷逼买不起,放弃。
freeModbus以前用过,但是好久没有更新了,放弃。最近更新是三年前。
libModbus还在正常维护。最新版本是 3.1.6,更新日期为 2019 年 9 月。

编译 libModbus

环境

Win10系统,编译器为 Visual Studio 2019。没有使用 MSYS2 或者 CYGWin 来编译。

生成 sln

这个不是我手动生成的,老版本里有。从老版本中拷贝过来即可。对应的文件在 libmodbus-3.1.6/src/win32 这个目录。

编译 DLL

错误1:缺少 config.h

将 libmodbus-3.1.6 目录下 config.h.in 拷贝过来,改名为 config.in 即可。

错误2:LNK111

如下:
在这里插入图片描述
是因为设置的版本号为 1.0.0 导致的语法错误。

解决方案

删除版本号就可以解决问题。在设置(项目>设置>链接器)上删除“版本”条目。如下图。
在这里插入图片描述
删除上图中的 1.0.0,即可解决这个问题。

结果

在这里插入图片描述
如上图所示,modbus.dll 和 modbus.lib 就生成成功。

测试libModbus

必须软件

Modbus Master

推荐使用 Modbus Poll 软件。

Modbus Slave

推荐使用 Modbus Slave 软件。

虚拟串口

如果没有现成的 Modbus 设备或者第二台计算机。那么虚拟串口就是必须的。
推荐使用:vspd虚拟串口软件。该软件可以虚拟出配对的两个串口。这样我们就可以运行 Modbus 软件来测试了。
软件安装好,运行起来如下图:
在这里插入图片描述
如上图,我的工控机有物理串口 7 7 7 个。虚拟串口一对。如果没有虚拟串口,选择添加即可。

虚拟串口测试
Modbus Master

在这里插入图片描述
如上图,打开 COM9,配置为 9600 N 8 1,使用 Modbus RTU 协议。

Modbus Slave

在这里插入图片描述
如上图,使用 COM10,9600 N 8 1,Modbus RTU 协议。
这样就可以发现两个软件成功开始通信。
在这里插入图片描述

Modbus Master 测试

VSDP + Modbus Poll + 自己的程序作为一个主机。这样我们只需要向串口发送 03 00 00 00 0A C5 CD 这个指令就可以了。

添加 Modbus Master RTU 项目

在 Visual Studio 2019 中选择“文件”->“新建”->“项目”。选择 C++ 空项目。配置如下图所示:
在这里插入图片描述
项目建立后。如下图所示。
在这里插入图片描述

RTU代码

在 RTU_Master 中添加一个空白的 cpp 文件,名字为 rtu_master.cpp,并加入到项目中。

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
//#include <windows.h>
#include "modbus.h"

#pragma comment(lib, "modbus.lib")
#pragma comment(lib, "ws2_32.lib")

int main(int argc, char* argv[]) {
    modbus_t* ctx;
    int rc;
    uint16_t tab_reg[64];

    //打开
    ctx = modbus_new_rtu("COM9", 9600, 'N', 8, 1);
    if (modbus_connect(ctx) == -1) {
        fprintf(stderr, "Connection failed: %s\n",
            modbus_strerror(errno));
        modbus_free(ctx);

    }
    //打开调试模式
    modbus_set_debug(ctx, 1);
    modbus_set_response_timeout(ctx, 1, 0);//设置响应时间

    //设置从机地址
    modbus_set_slave(ctx, 1);
    for (int i = 1; i <= 100; i++) {
        rc = modbus_read_registers(ctx, 0x00, 0x0A, tab_reg);
        //rc = modbus_read_input_registers(ctx, 0x00, 0x0A, tab_reg);
        if (rc == -1) {
            fprintf(stderr, "%s\n", modbus_strerror(errno));
            return -1;
        }
        //输出结果
        for (int j = 0; j < rc; j++) {
            printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
        }
        Sleep(1000);
    }

    //关闭设备
    modbus_close(ctx);
    modbus_free(ctx);

    return 0;
}


配置头文件路径

这个程序中,我们需要使用到 modbus.h。所以需要指定对应的路径。如下图所示。
在这里插入图片描述

配置库文件路径

这个程序中,我们需要使用到 modbus.lib。所以需要指定对应的路径。如下图所示。
在这里插入图片描述

配置DLL文件路径

这个程序中,我们需要使用到 modbus.dll。所以需要指定对应的路径。如下图所示。
在这里插入图片描述

运行结果

在这里插入图片描述
上图的数据解码有问题。先不管了。

添加 Modbus Master TCP 项目
TCP代码
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
//#include <windows.h>
#include "modbus.h"
#ifdef _WIN32
# include <winsock2.h>
#else
# include <sys/socket.h>
#endif

#pragma comment(lib, "modbus.lib")
#pragma comment(lib, "ws2_32.lib")

int main(int argc, char* argv[]) {
    modbus_t* ctx;
    int rc;
    uint16_t tab_reg[64];

    //打开
    ctx = modbus_new_tcp("127.0.0.1", 1502);
    //打开调试模式
    modbus_set_debug(ctx, 1);
    modbus_set_response_timeout(ctx, 1, 0);//设置响应时间
    //设置从机地址
    modbus_set_slave(ctx, 1);

    if (modbus_connect(ctx) == -1) {
        fprintf(stderr, "Connection failed: %s\n",
            modbus_strerror(errno));
        modbus_free(ctx);
    }

#if 0
    int server_socket = modbus_tcp_listen(ctx, 1);
    if (server_socket == -1) {
        fprintf(stderr, "Unable to listen TCP: %s\n",
            modbus_strerror(errno));
        modbus_free(ctx);
    }
    //modbus_tcp_accept(ctx, &server_socket);
#endif

    for (int i = 1; i <= 100; i++) {
        rc = modbus_read_registers(ctx, 0x00, 0x0A, tab_reg);
        //rc = modbus_read_input_registers(ctx, 0x00, 0x0A, tab_reg);
        if (rc == -1) {
            fprintf(stderr, "%s\n", modbus_strerror(errno));
            return -1;
        }
        //输出结果
        for (int j = 0; j < rc; j++) {
            printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
        }
        Sleep(1000);
    }

    //if (server_socket != -1) {
        //close(server_socket);
    //}

    //关闭设备
    modbus_close(ctx);
    modbus_free(ctx);

    return 0;
}

运行结果

在这里插入图片描述
上图的数据解码有问题。先不管了。

Modbus Slave 测试

待补充。今天先测试到这里,还有别的事情需要去搬砖。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的老周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值