工业总线modbus协议怎么玩

Posted by LuckXiang on July 3, 2018

工业总线协议都是比较简单的,其实不管什么协议都不难,只要你愿意仔仔细细的看看协议的标准.这里具体协议我就不讲了,主要介绍一下通过libmodbus来搭建自己的通信协议,libmodbus是github上一个开源的modbus实现,维护的比较好,项目地址如下https://github.com/stephane/libmodbus;拿到源码之后编译如下:

./autogen.sh
./configure --host=arm-linux-gnueabihf --prefix=/home/luckyxiang/Workspace/github/libmodbus/build
make
make install

我这里是交叉编译,通过–host指定编译工具链,然后–prefix指定安装目录,这样编译出来是动态so库,如果需要静态编译,去修改src目录下的Makefile文件,加上-static选项,’CFLAGS = -g -O2 -static’

放一段demo代码,

int modbus_data_get(void)
{
    modbus_t *ctx = NULL;
    int ret = -1;
    uint16_t tab_rp_bits[DATA_FRAME];
    int i = 0;
    int k = 0;

    printf("work satrt....\n");

    ctx = modbus_new_rtu("/dev/ttyO2", 9600, 'N', 8, 1);
    if(ctx == NULL)
    {
        printf("Unable to allocate libmodbus context\n");
        return -1;
    }
  //  modbus_set_debug(ctx, TRUE);
 //   modbus_set_error_recovery(ctx,
   //                           MODBUS_ERROR_RECOVERY_LINK |
     //                         MODBUS_ERROR_RECOVERY_PROTOCOL);
    modbus_set_slave(ctx, SERVER_ID);
    if (modbus_connect(ctx) == -1)
    {
        printf("Connection failed: %s\n", modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }
    memset(tab_rp_bits, 0, DATA_FRAME);
    for(k = 0; k < 100; k++)
    {
        ret = modbus_read_registers(ctx, UT_BITS_ADDRESS + k * DATA_FRAME, DATA_FRAME, tab_rp_bits);
        for(i = 0; i < DATA_FRAME; i++)
        {
            if(i != (DATA_FRAME - 1))
                printf("%d-", tab_rp_bits[i]);
            else
                printf("%d", tab_rp_bits[i]);
        }
        printf("\n");
    }
    modbus_free(ctx);
}

  • 第一步: modbus_new_rtu,我用的是485接口,485和232都是硬件协议,上边跑的软件一般都是串口协议,所以我这里需要配置相关参数.如果是其他协议的可以去看源码里边的test代码.
  • 第二步: modbus_set_slave 设置主机地址
  • 第三步: modbus_connect 这里会去打开串口设备
  • 第四步: modbus_read_registers 读取数据,注意还有其他读取数据的函数,这个是读功能码03的,协议上是读保存寄存器,第二个参数是寄存器地址,第三个是读取的数据长度,第四个是buf
  • 第五步: modbus_free 退出系统的时候释放串口和空间
  • 注意: 可以打开modbus_set_debug查看通信过程.