美文网首页
modbus之libmodbus

modbus之libmodbus

作者: 炎鸿 | 来源:发表于2019-10-11 04:25 被阅读0次

    一、libmodbus简介

    libmodbus是一个快速且可移植的Modbus库,支持传统的RS-232、RS-422、RS-485和以太网设备。

    二、安装libmodbus

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

    三、简单示例

    • 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: %s\n", 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, "%s\n", 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流程总结:
    1. 初始化 modbus 指针
    2. 设置从站ID
    3. 建立连接
    4. 读取保持寄存器/输入寄存器/离散输入/线圈输入
    5. 写单个寄存器/多个寄存器/多位数据
    6. 关闭连接
    • 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: %s\n", 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: %s\n",
                    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: %s\n", modbus_strerror(errno));
    
        modbus_mapping_free(mb_mapping);
        if (s != -1) {
            close(s);
        }
        modbus_close(ctx);
        modbus_free(ctx);
    }
    

    RTU-Slave流程总结:

    1. 初始化 modbus 指针;
    2. 设置从站ID;
    3. modbus_mapping_new初始化寄存器,返回一个modbus_mapping_t 指针;
    4. 建立连接;
    5. 调用 modbus_receive 函数判断串口的接收数据,负责接收处理及回复。
    • 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: %s\n", 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: %s\n",
                    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: %s\n", modbus_strerror(errno));
    
        modbus_mapping_free(mb_mapping);
        if (s != -1) {
            close(s);
        }
        modbus_close(ctx);
        modbus_free(ctx);
    }
    

    相关文章

      网友评论

          本文标题:modbus之libmodbus

          本文链接:https://www.haomeiwen.com/subject/jvbzpctx.html