本节主要记录一下学习modbus的编程实践,给出了一个读取modbus数据的示例。

数据提供源是Win上的Modbus Slave软件。

依赖库是libmodbus

下面的示例使用C语言提供,用于读取Modbus寄存器数据。

支持的数据个数分为四种:

  1. 6个线圈寄存器数据,读出数据保存在uint8_t数组中。
  2. 6个离散输入寄存器数据,同上。
  3. 20个输入寄存器数据,以16字节为单位,保存在uint16_t数组中。
  4. 20个保持寄存器数据,同上。

详细示例代码如下:

#include "modbus/modbus-tcp.h"

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define ADDRESS "192.168.157.1"

#define debug(fmt, ...) fprintf(stderr, "[%s %d]" fmt "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)

int main(void)
{
    modbus_t* modbus_ctx;
    uint8_t coil[6];
    uint8_t input_status[6];
    uint16_t input_reg[16 * 20];
    uint16_t hold_reg[16 * 20];

    int rc;

    modbus_ctx = modbus_new_tcp(ADDRESS, 502);
    if (modbus_ctx == NULL)
    {
        fprintf(stderr, "Unable to allocate libmodbus context");
        return -1;
    }
    modbus_set_debug(modbus_ctx, 1);  // 设置1可看到调试信息
    rc = modbus_connect(modbus_ctx);
    if (rc < 0)
    {
        debug("Connection failed: %s", modbus_strerror(errno));
        modbus_free(modbus_ctx);
        return -1;
    }

    while (1)
    {
        /* 1. 读取线圈寄存器数据,结果保存在uint8_t数组中 */
        memset(&coil, 0x00, sizeof(coil));
        rc = modbus_read_bits(modbus_ctx, 0x00000, 6, coil);
        if (rc == -1)
        {
            debug("%s", modbus_strerror(errno));
            modbus_free(modbus_ctx);
            return -1;
        }
        for (int i = 0; i < rc; i++)
            debug("reg[%d]=%d (0x%X)", i, coil[i], coil[i]);

        /* 2. 读取离线输入寄存器数据,结果保存在uint8_t数组中 */
        memset(&input_status, 0x00, sizeof(input_status));
        rc = modbus_read_bits(modbus_ctx, 0x10000, 6, input_status);
        if (rc == -1)
        {
            debug("%s\n", modbus_strerror(errno));
            modbus_free(modbus_ctx);
            return -1;
        }
        for (int i = 0; i < rc; i++)
            debug("reg[%d]=%d (0x%X)", i, input_status[i], input_status[i]);

        /* 3. 读取输入寄存器数据,保存在uint16_t数组中 */
        rc = modbus_read_input_registers(modbus_ctx, 0x30000, 20, input_reg);
        if (rc == -1)
        {
            debug("%s", modbus_strerror(errno));
            modbus_free(modbus_ctx);
            return -1;
        }
        for (int i = 0; i < rc; i++)
            debug("reg[%d]=%d (0x%X)", i, input_reg[i], input_reg[i]);

        /* 4. 读取保持寄存器数据,保存在uint16_t数组中 */
        rc = modbus_read_registers(modbus_ctx, 0x40000, 20, hold_reg);
        if (rc == -1)
        {
            debug("%s", modbus_strerror(errno));
            modbus_free(modbus_ctx);
            return -1;
        }
        for (int i = 0; i < rc; i++)
            debug("reg[%d]=%d (0x%X)", i, hold_reg[i], hold_reg[i]);
            
        usleep(1000000);
    }

    modbus_close(modbus_ctx);
    modbus_free(modbus_ctx);
}

读取输出结果如下:

Connecting to 192.168.157.1:502
[00][01][00][00][00][06][FF][01][00][00][00][06]
Waiting for a confirmation...
<00><01><00><00><00><04><FF><01><01><08>
[main 52]reg[0]=0 (0x0)
[main 52]reg[1]=0 (0x0)
[main 52]reg[2]=0 (0x0)
[main 52]reg[3]=1 (0x1)
[main 52]reg[4]=0 (0x0)
[main 52]reg[5]=0 (0x0)
[00][02][00][00][00][06][FF][01][00][00][00][06]
Waiting for a confirmation...
<00><02><00><00><00><04><FF><01><01><08>
[main 64]reg[0]=0 (0x0)
[main 64]reg[1]=0 (0x0)
[main 64]reg[2]=0 (0x0)
[main 64]reg[3]=1 (0x1)
[main 64]reg[4]=0 (0x0)
[main 64]reg[5]=0 (0x0)
[00][03][00][00][00][06][FF][04][00][00][00][14]
Waiting for a confirmation...
<00><03><00><00><00><2B><FF><04><28><43><71><1E><B8><00><00><00><00><00><00><00><00><65><68><6C><6C><77><6F><72><6F><64><6C><00><00><00><00><00><00><00><7B><00><00><00><00><00><00><00><00><00><00>
[main 75]reg[0]=17265 (0x4371)
[main 75]reg[1]=7864 (0x1EB8)
[main 75]reg[2]=0 (0x0)
[main 75]reg[3]=0 (0x0)
[main 75]reg[4]=0 (0x0)
[main 75]reg[5]=0 (0x0)
[main 75]reg[6]=25960 (0x6568)
[main 75]reg[7]=27756 (0x6C6C)
[main 75]reg[8]=30575 (0x776F)
[main 75]reg[9]=29295 (0x726F)
[main 75]reg[10]=25708 (0x646C)
[main 75]reg[11]=0 (0x0)
[main 75]reg[12]=0 (0x0)
[main 75]reg[13]=0 (0x0)
[main 75]reg[14]=123 (0x7B)
[main 75]reg[15]=0 (0x0)
[main 75]reg[16]=0 (0x0)
[main 75]reg[17]=0 (0x0)
[main 75]reg[18]=0 (0x0)
[main 75]reg[19]=0 (0x0)
[00][04][00][00][00][06][FF][03][00][00][00][14]
Waiting for a confirmation...
<00><04><00><00><00><2B><FF><03><28><FB><2E><30><39><80><0D><C8><A7><00><18><C8><87><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00>
[main 86]reg[0]=64302 (0xFB2E)
[main 86]reg[1]=12345 (0x3039)
[main 86]reg[2]=32781 (0x800D)
[main 86]reg[3]=51367 (0xC8A7)
[main 86]reg[4]=24 (0x18)
[main 86]reg[5]=51335 (0xC887)
[main 86]reg[6]=0 (0x0)
[main 86]reg[7]=0 (0x0)
[main 86]reg[8]=0 (0x0)
[main 86]reg[9]=0 (0x0)
[main 86]reg[10]=0 (0x0)
[main 86]reg[11]=0 (0x0)
[main 86]reg[12]=0 (0x0)
[main 86]reg[13]=0 (0x0)
[main 86]reg[14]=0 (0x0)
[main 86]reg[15]=0 (0x0)
[main 86]reg[16]=0 (0x0)
[main 86]reg[17]=0 (0x0)
[main 86]reg[18]=0 (0x0)
[main 86]reg[19]=0 (0x0)
[00][05][00][00][00][06][FF][01][00][00][00][06]
Waiting for a confirmation...
<00><05><00><00><00><04><FF><01><01><09>
[main 52]reg[0]=1 (0x1)
[main 52]reg[1]=0 (0x0)
[main 52]reg[2]=0 (0x0)
[main 52]reg[3]=1 (0x1)
[main 52]reg[4]=0 (0x0)
[main 52]reg[5]=0 (0x0)
[00][06][00][00][00][06][FF][01][00][00][00][06]
Waiting for a confirmation...
<00><06><00><00><00><04><FF><01><01><09>
[main 64]reg[0]=1 (0x1)
[main 64]reg[1]=0 (0x0)
[main 64]reg[2]=0 (0x0)
[main 64]reg[3]=1 (0x1)
[main 64]reg[4]=0 (0x0)
[main 64]reg[5]=0 (0x0)
[00][07][00][00][00][06][FF][04][00][00][00][14]
Waiting for a confirmation...
<00><07><00><00><00><2B><FF><04><28><43><71><1E><B8><00><00><00><00><00><00><00><00><65><68><6C><6C><77><6F><72><6F><64><6C><00><00><00><00><00><00><00><7B><00><00><00><00><00><00><00><00><00><00>
[main 75]reg[0]=17265 (0x4371)
[main 75]reg[1]=7864 (0x1EB8)
[main 75]reg[2]=0 (0x0)
[main 75]reg[3]=0 (0x0)
[main 75]reg[4]=0 (0x0)
[main 75]reg[5]=0 (0x0)
[main 75]reg[6]=25960 (0x6568)
[main 75]reg[7]=27756 (0x6C6C)
[main 75]reg[8]=30575 (0x776F)
[main 75]reg[9]=29295 (0x726F)
[main 75]reg[10]=25708 (0x646C)
[main 75]reg[11]=0 (0x0)
[main 75]reg[12]=0 (0x0)
[main 75]reg[13]=0 (0x0)
[main 75]reg[14]=123 (0x7B)
[main 75]reg[15]=0 (0x0)
[main 75]reg[16]=0 (0x0)
[main 75]reg[17]=0 (0x0)
[main 75]reg[18]=0 (0x0)
[main 75]reg[19]=0 (0x0)
[00][08][00][00][00][06][FF][03][00][00][00][14]
Waiting for a confirmation...
<00><08><00><00><00><2B><FF><03><28><FB><2E><30><39><80><0D><C8><A7><00><18><C8><87><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00>
[main 86]reg[0]=64302 (0xFB2E)
[main 86]reg[1]=12345 (0x3039)
[main 86]reg[2]=32781 (0x800D)
[main 86]reg[3]=51367 (0xC8A7)
[main 86]reg[4]=24 (0x18)
[main 86]reg[5]=51335 (0xC887)
[main 86]reg[6]=0 (0x0)
[main 86]reg[7]=0 (0x0)
[main 86]reg[8]=0 (0x0)
[main 86]reg[9]=0 (0x0)
[main 86]reg[10]=0 (0x0)
[main 86]reg[11]=0 (0x0)
[main 86]reg[12]=0 (0x0)
[main 86]reg[13]=0 (0x0)
[main 86]reg[14]=0 (0x0)
[main 86]reg[15]=0 (0x0)
[main 86]reg[16]=0 (0x0)
[main 86]reg[17]=0 (0x0)
[main 86]reg[18]=0 (0x0)
[main 86]reg[19]=0 (0x0)