MAC Book Pro 使用 libmodbus

写在前面

帮助朋友调试 MODBUS 通信设备,MODBUS 协议栈以前写过,但是这次也不想自己从头写一个 MODBUS 协议栈,太烦了。所以在 GitHub 上找到了 libModbus。

libModubs

官网地址为 https://www.libmodbus.org/。提供一个标准 C 实现的 Modbus 协议栈。支持 TCP 和 RTU。
该协议栈支持 Linux, Mac OS X, Win32 等系统。

工作环境搭建

设备状态

机器:Mac Book Pro。
GCC版本:4.2.1。机器显示如下:

% gcc --version                                                
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 12.0.0 (clang-1200.0.32.2)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

libModbus 版本:使用最新的 3.1.6。
MODBUS设备:两个485接口的温湿度传感器,一个地址为 0x02,一个地址为 0x03。

MBP USB 转串口

我使用了一个 USB 转 485,内部芯片为 CH341。该芯片提供 Mac 的驱动。对应的下载地址为:http://www.wch.cn/download/CH341SER_MAC_ZIP.html。
下载后,安装对应驱动。插入 USB 转 485 设备。

% ls /dev/tty.
tty.Bluetooth-Incoming-Port%  tty.usbserial-1410%

如上所示,tty.usbserial-1410 就是我机器上的串口。

串口调试助手

在苹果商店搜索“串口调试助手”,下载安装即可。
MAC Book Pro 使用 libmodbus_第1张图片
上图就是在 MBP 上运行和设备通信的情况。

编译 libModbus

支持库

需要安装 autoconf、automake、libtool。可以使用命令行:
brew install autoconf automake libtool
进行安装。

编译 libModbus

解压文件,进入到对应的目录。使用命令行
./configure && make install
一般情况下,不会出现任何错误。
这样对应的库文件会安装在 /usr/local/lib 下。

% ls /usr/local/lib/libmo
libmodbus.5.dylib*        libmodbus.la*             libmongoose.2.dylib@      libmongoose.dylib@
libmodbus.dylib@          libmongoose.2.0.4.dylib@  libmongoose.a@            libmongoose_dbg.a@

如上所示,这样 libModbus 就编译好了。
头文件将安装在 /usr/local/include/modbus 目录下。

% ls /usr/local/include/modbus/      
modbus-rtu.h		modbus-tcp.h		modbus-version.h	modbus.h

通信测试

本次设备为温湿度传感器。

获取温度

发送:02 04 00 01 00 01 60 39。
其中 02 表示设备地址,04 表示 Modbus 功能码,00 01 表示寄存器地址为 1,00 01 表示数据长度为 1,60 39 是 CRC 校验。
将获得:02 04 02 01 2B BC BF
其中 02 表示设备地址,04 表示 Modbus 功能码,02 表示数据长度,01 2B 表示数据内容,BC BF 是 CRC 校验。
0x012B 对应的 10 进制数据为 299,也就是说温度为 29.9 摄氏度。

获取湿度

发送:02 04 00 02 00 01 90 39。
将获得:02 04 02 01 D5 3D 3F。
对应的湿度是 0x01D5,转换成十进制为 469,对应的湿度为 46.9%。

测试代码

测试代码如下,使用标准 C,代码中都有注释。

#include 
#include 
#include 
#include 
#include 

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

    //打开
    ctx = modbus_new_rtu("/dev/tty.usbserial-1410", 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, 2);
    /* 从 1 寄存器读取 1 个地址,这样获得温度*/
    rc = modbus_read_input_registers(ctx, 1, 1, tab_reg);
    if (rc == -1) {
        fprintf(stderr, "%s\n", modbus_strerror(errno));
        return -1;
    }
    //输出结果
    for (int i=0; i < rc; i++) {
        printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
    }
    usleep(20000);

    /* 从 2 寄存器读取 1 个地址,这样获得湿度*/
    rc = modbus_read_input_registers(ctx, 2, 1, tab_reg);
    if (rc == -1) {
        fprintf(stderr, "%s\n", modbus_strerror(errno));
        return -1;
    }
    //输出结果
    for (int i=0; i < rc; i++) {
        printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
    }
    usleep(20000);

    //设置从机地址
    modbus_set_slave(ctx, 3);
    /* 从 1 寄存器读取 1 个地址,这样获得温度*/
    rc = modbus_read_input_registers(ctx, 1, 1, tab_reg);
    if (rc == -1) {
        fprintf(stderr, "%s\n", modbus_strerror(errno));
        return -1;
    }
    //输出结果
    for (int i=0; i < rc; i++) {
        printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
    }
    usleep(20000);

    /* 从 2 寄存器读取 1 个地址,这样获得湿度*/
    rc = modbus_read_input_registers(ctx, 2, 1, tab_reg);
    if (rc == -1) {
        fprintf(stderr, "%s\n", modbus_strerror(errno));
        return -1;
    }
    //输出结果
    for (int i=0; i < rc; i++) {
        printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
    }
    usleep(20000);

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

    return 0;
}

编译

% gcc mytest.c -o mytest `pkg-config --libs --cflags libmodbus`

这样将得到可执行文件 mytest。

运行

% ./mytest 
[02][04][00][01][00][01][60][39]
Waiting for a confirmation...
<02><04><02><01><3A><7C><B3>
reg[0]=314 (0x13A)
[02][04][00][02][00][01][90][39]
Waiting for a confirmation...
<02><04><02><01><B9><3D><12>
reg[0]=441 (0x1B9)
[03][04][00][01][00][01][61][E8]
Waiting for a confirmation...
<03><04><02><01><34><C0><B7>
reg[0]=308 (0x134)
[03][04][00][02][00][01][91][E8]
Waiting for a confirmation...
<03><04><02><01><C3><81><31>
reg[0]=451 (0x1C3)

可以看到获得的数据和上面解析的数据一致。说明已经可以使用 libModbus 进行 Modbus RTU 通信。

下一步工作

测试代码已经完成,下面开始写正式的工程代码。

你可能感兴趣的:(笔记,MBP,libModbus,MODBUS,RTU,物联网)