Libmodbus - Modbus library for Linux, Mac OS, FreeBSD, Windows

freeFree Technical Resource

This content is free to read, suitable for basic learning and search traffic.

Libmodbus - Modbus library for Linux, Mac OS, FreeBSD, Windows缩略图

Overview

Libmodbus is a fast and portable Modbus library that supports traditional RS-232, RS-422, RS-485, and Ethernet devices.

Install

Linux, MacOS, FreeBSD, WIN32, etc. can be installed directly through the package managerlibmodbus

libmodbus official website download:https://libmodbus.org/releases/libmodbus-3.1.7.tar.gz
GitHub Download:https://github.com/stephane/libmodbus.git

//进入解压目录
cd libmodbus-3.1.7
//配置编译选项(以ARM为例,--build为系统构架 --host为编译对应系统工具链,--prefix为输出目录,选项均是可选的)
./configure --build=i686 --host=arm-linux --enable-static --prefix=[install path]/
//编译安装
make && make install

Example

RTU master

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "modbus.h"

int main(void)
{ 
    int i = 0;
    int regs = 0;
    modbus_t *ctx = NULL;
    uint16_t tab_reg[64] = {0};

    //打开端口: 端口,波特率,校验位,数据位,停止位
    ctx = modbus_new_rtu("/dev/ttyUSB0", 9600, 'N', 8, 1);
    //设置从机地址
    modbus_set_slave(ctx, 1);
    //设置串口模式(可选)
    modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485);
    //设置RTS(可选)
    modbus_rtu_set_rts(ctx, MODBUS_RTU_RTS_UP);
    //建立连接
    if (modbus_connect(ctx) == -1) {
        fprintf(stderr, "Connexion failed: %sn", modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }
    //设置应答延时(可选)
    modbus_set_response_timeout(ctx, 0, 1000000);

    while (1)
    {
        memset(tab_reg, 0, sizeof(tab_reg));
        //读寄存器设置:寄存器地址、数量、数据缓冲
        regs = modbus_read_registers(ctx, 0, 20, tab_reg);
        if (rc == -1) {
           fprintf(stderr, "%sn", modbus_strerror(errno));
           continue;
        }
        printf("[%4d][read num = %d]", num++, regs);
        for (i = 0; i < 20; ++i)
        {
            printf("<%#x>", tab_reg[i]);
        }
        printf("n");
        sleep(1);
    }
}
  • RTU Master Process Summary:
  1. Initialize Modbus Pointer
  2. Set Slave ID
  3. Establish connection
  4. Read hold register/input register/discrete input/coil input
  5. Write single register/multiple registers/multi bit data
  6. Close connection

RTU slave

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <error.h>
#include <memory.h>
#include "modbus.h"

int main(void)
{ 
    int i = 0;
    int rc = 0;
    modbus_t *ctx = NULL;
    modbus_mapping_t *mb_mapping = NULL;
    uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];

    //打开端口: 端口,波特率,校验位,数据位,停止位
    ctx = modbus_new_rtu("/dev/ttyUSB0", 9600, 'N', 8, 1);
    //设置从机地址
    modbus_set_slave(ctx, 1);
    //设置串口模式
    //modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485);
    //设置RTS
    //modbus_rtu_set_rts(ctx, MODBUS_RTU_RTS_UP);
    //建立连接
    if (modbus_connect(ctx) == -1) {
        fprintf(stderr, "Connexion failed: %sn", modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }
    mb_mapping = modbus_mapping_new(MODBUS_MAX_READ_BITS, 0,
                                    MODBUS_MAX_READ_REGISTERS, 0);
    if (mb_mapping == NULL) {
        fprintf(stderr, "Failed to allocate the mapping: %sn",
                modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }

   //初始化几个寄存器
   mb_mapping->tab_registers[0] = 1;
   mb_mapping->tab_registers[1] = 2;
   mb_mapping->tab_registers[2] = 3;
   mb_mapping->tab_registers[3] = 4;
   mb_mapping->tab_registers[4] = 5;
   mb_mapping->tab_registers[5] = 6;

    while (1)
    {
        memset(query, 0, sizeof(query));
        rc = modbus_receive(ctx, query);
        if (rc > 0) {
            modbus_reply(ctx, query, rc, mb_mapping);
        } else if (rc  == -1) {
            //Connection closed by the client or error
            break;
        }
    }

    printf("Quit the loop: %sn", modbus_strerror(errno));

    modbus_mapping_free(mb_mapping);
    if (s != -1) {
        close(s);
    }
    modbus_close(ctx);
    modbus_free(ctx);
}

RTU Slave process summary:

  1. Initialize Modbus pointer;
  2. Set slave ID;
  3. The modbus_mapping_new initialization register returns a modbus_mapping_t pointer;
  4. Establish a connection;
  5. Call the modbus_deceive function to determine the received data of the serial port, responsible for receiving, processing, and replying.

TCP master

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <error.h>
#include <memory.h>
#include <sys/socket.h>
#include "modbus.h"

void main(void)
{
    int i;
    int regs = 0;
    int num = 0;
    modbus_t *ctx = NULL;
    uint16_t tab_reg[64] = {0};
   
    ctx = modbus_new_tcp("127.0.0.1",8000);
    modbus_set_slave(ctx, 1);
    modbus_connect(ctx);
    modbus_set_response_timeout(ctx, 0, 1000000);
   
    while (1)
    {
        memset(tab_reg, 0, sizeof(tab_reg));
        regs = modbus_read_registers(ctx, 0, 20, tab_reg);
        printf("[%4d][read num = %d]", num++, regs);
        for (i = 0; i < 20; i++)
        {
            printf("<%#x>", tab_reg[i]);
        }
        printf("n");
        sleep(1);
    }

    modbus_close(ctx);
    modbus_free(ctx);
}

TCP slave

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <error.h>
#include <memory.h>
#include <sys/socket.h>
#include "modbus.h"

int main(void)
{ 
    int i = 0;
    int rc = 0;
    modbus_t *ctx = NULL;
    modbus_mapping_t *mb_mapping = NULL;
    uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];

    //打开端口: ip, port
    ctx = modbus_new_tcp("127.0.0.1", 8000);
    //设置从机地址
    modbus_set_slave(ctx, 1);
    //建立连接
    if (modbus_connect(ctx) == -1) {
        fprintf(stderr, "Connexion failed: %sn", modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }
    mb_mapping = modbus_mapping_new(MODBUS_MAX_READ_BITS, 0,
                                    MODBUS_MAX_READ_REGISTERS, 0);
    if (mb_mapping == NULL) {
        fprintf(stderr, "Failed to allocate the mapping: %sn",
                modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }

   //初始化几个寄存器
   mb_mapping->tab_registers[0] = 1;
   mb_mapping->tab_registers[1] = 2;
   mb_mapping->tab_registers[2] = 3;
   mb_mapping->tab_registers[3] = 4;
   mb_mapping->tab_registers[4] = 5;
   mb_mapping->tab_registers[5] = 6;

    while (1)
    {
        memset(query, 0, sizeof(query));
        rc = modbus_receive(ctx, query);
        if (rc > 0) {
            modbus_reply(ctx, query, rc, mb_mapping);
        } else if (rc  == -1) {
            //Connection closed by the client or error
            break;
        }
    }

    printf("Quit the loop: %sn", modbus_strerror(errno));

    modbus_mapping_free(mb_mapping);
    if (s != -1) {
        close(s);
    }
    modbus_close(ctx);
    modbus_free(ctx);
}

Put this resource to use in a real project?

Go to the Tool Center for message parsing, CRC verification and device debugging, or submit your requirements for selection and integration advice.

Engineer Membership

Turn this article into actionable debugging resources

After activation, you can use advanced message parsing, resource pack downloads, code examples, engineering cases and priority technical support, suitable for real project delivery.

Unlimited Advanced Tools
Resource & Code Packs
Complete Engineering Case Library
Priority Technical Support

《 “Libmodbus - Modbus library for Linux, Mac OS, FreeBSD, Windows” 》 有 6 条Comments

Leave a Reply

Your email address will not be published. Required fields are marked *.