如何使用libmodbus进行“读/写”功能?(C代码)

时间:2019-10-31 16:04:00

标签: modbus modbus-tcp

我要根据modbus-tcp规范进行读取/写入。 因此,我正在尝试在linux环境中对客户端和服务器进行编码。 (我将使用modbus-tcp与Windows程序(作为客户端)进行通信。)

但是它不能按我的意愿工作,所以我在这里问你。

  1. 我正在测试作为客户端的linux和作为服务器的easymodbus的客户端代码。
  2. 我使用了libmodbus代码。
  3. 我想读取线圈(0x01)和写入线圈(0x05)。
  4. 使用libmodbus执行代码时,从单元ID部分打印出'ff'。(根据手册,对于modbus-tcp,应输出01。 我不知道为什么要打印'ff'(附照片)。

错误的结果:

Wrong result

预期结果:

Expected result

  1. '[00] [00] .... [00]';你知道哪里可以控制这部分吗?
  2. 您是否拥有或知道使用libmodbus实现“读/写”功能的示例代码?

请告知我有关信息。

ctx = modbus_new_tcp("192.168.0.99", 502);
modbus_set_debug(ctx, TRUE);

if (modbus_connect(ctx) == -1) {
    fprintf(stderr, "Connection failed: %s\n",
            modbus_strerror(errno));
    modbus_free(ctx);
    return -1;
}

tab_rq_bits = (uint8_t *) malloc(nb * sizeof(uint8_t));
memset(tab_rq_bits, 0, nb * sizeof(uint8_t));

tab_rp_bits = (uint8_t *) malloc(nb * sizeof(uint8_t));
memset(tab_rp_bits, 0, nb * sizeof(uint8_t));

nb_loop = nb_fail = 0;

/* WRITE BIT */
rc = modbus_write_bit(ctx, addr, tab_rq_bits[0]);
if (rc != 1) {
    printf("ERROR modbus_write_bit (%d)\n", rc);
    printf("Address = %d, value = %d\n", addr, tab_rq_bits[0]);
    nb_fail++;
} else {
    rc = modbus_read_bits(ctx, addr, 1, tab_rp_bits);
    if (rc != 1 || tab_rq_bits[0] != tab_rp_bits[0]) {
        printf("ERROR modbus_read_bits single (%d)\n", rc);
        printf("address = %d\n", addr);
        nb_fail++;
    }
}   
printf("Test: ");
if (nb_fail)
    printf("%d FAILS\n", nb_fail);
else
    printf("SUCCESS\n");

free(tab_rq_bits);
free(tab_rp_bits);

/* Close the connection */
modbus_close(ctx);
modbus_free(ctx);

return 0;

2 个答案:

答案 0 :(得分:1)

您在Modbus功能实际正确之前看到的FF。引用Modbus Implementation Guide,第23页:

  

在TCP / IP上,使用其IP地址对MODBUS服务器进行寻址。因此,   MODBUS单元标识符无效。必须使用值0xFF。

因此 libmodbus 只是遵循Modbus规范。那么,我假设问题出在 easymodbus 中,这显然是希望您在查询中使用0x01作为单位ID。

我想您不想惹起 easymodbus ,因此您可以通过 libmodbus 轻松解决此问题:只需更改默认单位ID:

modbus_set_slave(ctx, 1);

您还可以选择:

 rc = modbus_set_slave(ctx, MODBUS_BROADCAST_ADDRESS);
 ASSERT_TRUE(rc != -1, "Invalid broadcast address");

如果您有多个,则使您的客户端访问网络中的所有从属。

libmodbus man page for modbus_set_slave function中提供了更多信息,并简要说明了此问题的出处。

举一个非常全面的例子,您可以查看libmodbus unit tests

关于第5个问题,我不知道该如何回答,您所指的零应该是您要向线圈写入(或读取)的状态(真或假)。为了进行编写,您可以使用函数modbus_write_bit(ctx, address, value)的value字段更改它们。

答案 1 :(得分:0)

非常感谢您的答复。

我使用您推荐的“ unit-test-server / client”代码测试了读/写功能。 我已经审查了代码,但是还有很多我不知道的事情。

但是,有一个地址值在使用unit-test-server / client代码相互测试之后起作用,并且有一个地址值不起作用 (你知道为什么吗?)。

-检查并发现UT_BITS_ADDRESS(地址值)的值在0x130至0x150之间运行  -“错误的非法数据地址”出现在-0x130以下和0x150以上的值  -我要读取/写入的地址是0x0001到0x0004(您知道该怎么办吗?)。

我想知道如何像右图的TX部分那样处理和传输数据。

enter image description here

我在Linux环境中同时运行客户端和服务器,并且正在执行读/写测试。 在错误的图片中... [06] [FF] ... <-我想知道如何修改FF部分(如图所示将值更改为01)

enter image description here

和“ modbus_set_slave”是modbus rtu的功能吗? 最后,我想交流一下PC程序和Linux设备。 那么我应该使用哪个功能呢?

再次感谢您的关注。