通信(三)Modbus

1. Mdobus

1.2 ModbusTCP

2. libmodbus库

libmodbus 是支持Linux,Mac OS X,window 的一个开源库,支持modbus TCP和modbus RTU 两种模式。

2.1 libmodbus下载

目录结果

  • docs目录 libmodbus库API接口说明文档
  • m4目录 存放GUN m4文件
  • src目录 libmodbus源代码
  • tests目录自带的测试代码

2.2 libmodbus编译动态库

打开src文件目录如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a7946991c6594b72a3de26f752bba60c.png
注意:

  • .js文件,双击js文件时需要选择打开方式时,右键打开方式选择【Microsoft ® Windows Based Script Host】
    在这里插入图片描述
  • 不能有中文路径,也不能放桌面

32位动态库

1、进入 src/win32 文件夹,双击src\win32\configure.js,生成一些配置文件,其中 modbus-version.h 被生成到上一级文件夹中,config.h生成在该路径下。
在这里插入图片描述
2、用Visual Studio 2019打开文件modbus-9.sln。
3、查看项目头文件下的modbus-version.h文件,发现路径不存在,此时移除此文件,在项目上右键添加现有项,找到上一步生成的modbus-version.h,其路径在win32的上一级目录。
4、32位下选择debug和release模式下分别编译,编译成功后在win32路径下生成对应的debug/release版本的modbus.dll和modbus.lib

64位动态库

1、进入 src/win32 文件夹,双击src\win32\configure.js,生成一些配置文件,其中 modbus-version.h 被生成到上一级文件夹中,config.h生成在该路径下。
在这里插入图片描述
2、用Visual Studio 2019打开文件modbus-9.sln。
3、查看项目头文件下的modbus-version.h文件,发现路径不存在,此时移除此文件,在项目上右键添加现有项,找到上一步生成的modbus-version.h,其路径在win32的上一级目录。
4、Visual Studio 2019将编译平台的配置管理器修改为release-x64,重新编译
在这里插入图片描述
5、编译后报LNK2019错误
在这里插入图片描述
6、原因是64位缺少依赖库ws2_32.lib,在属性-链接器-输入-附加依赖项-<编辑…>,添加后,重新编译
在这里插入图片描述在这里插入图片描述
7、编译后报LNK2019和LNK1120错误
在这里插入图片描述
8、原因是没有main函数,项目不能生成exe。属性-常规-配置类型-动态库(.dll),修改后,重新编译
在这里插入图片描述
9、64位下选择debug和release模式下分别编译,编译成功后在win32/x64/Release路径下生成对应modbus.dll和modbus.lib
在这里插入图片描述

3. C++

工程配置

  • pro文件配置
INCLUDEPATH += $$PWD/lib/libmodbus/include
LIBS        += $$PWD/lib/libmodbus/bin/modbus.lib

运行exe时,将modbus.dll copy到其路径下。

Modbus TCP 示例

Modbus TCP 服务器示例

#include <modbus.h>
#include <stdio.h>

int main()
{
    modbus_t *ctx = modbus_new_tcp("127.0.0.1", 502);
    modbus_mapping_t *mb_mapping;

    if (ctx == NULL) {
        fprintf(stderr, "Unable to create the libmodbus context\n");
        return -1;
    }

    mb_mapping = modbus_mapping_new(0, 0, 100, 0);
    if (mb_mapping == NULL) {
        fprintf(stderr, "Failed to allocate the mapping: %s\n", modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }

    while (true) {
        uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];
        int rc = modbus_receive(ctx, query);
        if (rc > 0) {
            modbus_reply(ctx, query, rc, mb_mapping);
        }
    }

    modbus_mapping_free(mb_mapping);
    modbus_close(ctx);
    modbus_free(ctx);

    return 0;
}

Modbus TCP 客户端示例

#include <modbus.h>
#include <stdio.h>

int main()
{
    modbus_t *ctx = modbus_new_tcp("127.0.0.1", 502);
    if (modbus_connect(ctx) == -1) {
        fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }

    uint16_t tab_reg[1];
    tab_reg[0] = 1234;

    int rc = modbus_write_registers(ctx, 0, 1, tab_reg);
    if (rc == 1) {
        printf("Write successful\n");
    } else {
        fprintf(stderr, "Write failed: %s\n", modbus_strerror(errno));
    }

    uint16_t read_reg;
    rc = modbus_read_registers(ctx, 0, 1, &read_reg);
    if (rc == 1) {
        printf("Read value: %d\n", read_reg);
    } else {
        fprintf(stderr, "Read failed: %s\n", modbus_strerror(errno));
    }

    modbus_close(ctx);
    modbus_free(ctx);

    return 0;
}

libmodbus函数说明

在Modbus通讯协议中,有几种常见的读取数据的函数,包括modbus_read_bits、modbus_read_input_bits和modbus_read_registers。这些函数用于读取不同类型的数据,下面是它们的区别:

函数用途说明
modbus_read_bits读取线圈(Coils)数据用于读取线圈(Coils)数据,即开关量数据。
线圈数据通常是输出数据,可由Modbus设备的控制逻辑进行操作。
线圈数据的地址范围是从0开始,通常用于控制或监控开关状态。
读取的数据是布尔类型,每个位代表一个开关状态。
modbus_read_input_bits读取输入线圈(Input Coils)数据用于读取输入线圈(Input Coils)数据,即输入开关量数据。
输入线圈数据通常是输入数据,表示外部设备的状态。
输入线圈数据的地址范围也是从0开始,通常用于监控外部设备状态。
读取的数据是布尔类型,每个位代表一个开关状态。
modbus_read_registers读取保持寄存器(Holding Registers)数据用于读取保持寄存器(Holding Registers)数据,即16位寄存器数据。
保持寄存器数据通常用于存储控制器内部的数据,如整数、浮点数等。
保持寄存器数据的地址范围也是从0开始,通常用于传输16位二进制数据。
读取的数据是16位整数类型。

在Modbus通讯协议中,MODBUS_FC_READ_COILS和MODBUS_FC_READ_DISCRETE_INPUTS是两种不同的功能码,用于读取不同类型的数据,分别是线圈(Coils)数据和离散输入(Discrete Inputs)数据。以下是它们的区别:

功能码说明
MODBUS_FC_READ_COILS0x01读取可写的输出线圈数据功能码为0x01,用于读取线圈(Coils)数据。
线圈数据通常是输出数据,可由Modbus设备的控制逻辑进行操作。
线圈数据的地址范围是从0开始,每个线圈代表一个开关状态。
读取的数据是布尔类型,每个位代表一个开关状态。
适用于读取可写的输出线圈数据。
MODBUS_FC_READ_DISCRETE_INPUTS0x02读取只读的输入线圈数据功能码为0x02,用于读取离散输入(Discrete Inputs)数据。
离散输入数据通常是输入数据,表示外部设备的状态。
离散输入数据的地址范围也是从0开始,每个位代表一个开关状态。
读取的数据是布尔类型,每个位代表一个开关状态。
适用于读取只读的输入线圈数据。

3. C#

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小老鼠不吃猫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值