首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用libmodbus的多个RS485从站

使用libmodbus的多个RS485从站
EN

Stack Overflow用户
提问于 2015-12-21 09:28:47
回答 1查看 2.5K关注 0票数 2

我在一条RS485总线上有多个从站。到目前为止,我一直在使用pymodbus,但我对它的性能和其他问题不太满意。所以我想测试一下libmodus并使用它。

我写了一个最小的程序来读取我的从属的型号

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <modbus.h>
#include <errno.h>


char *bigendian_vec_to_str(uint16_t *vec, size_t vec_size, char *buff, size_t buff_len)
{
    memset(buff, 0, sizeof *buff * buff_len);
    int i;

    for(i = 0; i < vec_size; ++i)
    {
        uint16_t fl = vec[i] >> 8;
        uint16_t sl = vec[i] & 0xff;

        if(2*i >= buff_len - 1)
            return buff;

        if(fl == 0)
            return buff;

        buff[2 * i] = fl;

        if(2*i + 1 >= buff_len - 1)
            return buff;

        if(sl == 0)
            return buff;

        buff[2 * i + 1] = sl;
    }

    return buff;
}

char *get_model_name_of(modbus_t *modbus, int slave, char *buff, size_t buff_len)
{
    modbus_flush(modbus);
    modbus_set_slave(modbus, slave);

    int rc; 
    uint16_t reg[9];

    memset(reg, 0, sizeof reg);

    rc = modbus_read_registers(modbus, 0xe, 8, reg);
    if (rc == -1) {
        fprintf(stderr, "Error %d while reading: %s\n", errno, modbus_strerror(errno));
        return NULL;
    }   
    return bigendian_vec_to_str(reg, 8, buff, buff_len);
}


int main(void)
{
    modbus_t *modbus = modbus_new_rtu("/dev/ttyUSB0", 9600, 'N', 8, 1);

    modbus_rtu_set_serial_mode(modbus, MODBUS_RTU_RS485);

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

    char buff[1024];
    int i;

    for(i = 2; i < 5; ++i)
    {
        printf("Model of slave %d: %s\n", i, get_model_name_of(modbus, i, buff, sizeof buff));
    }

    modbus_free(modbus);
    return 0;
}

当我运行这段代码时,我得到

代码语言:javascript
复制
Model of slave 2: LEFS25B-600
Error 110 while reading: Connection timed out
Model of slave 3: (null)
Model of slave 4: LEHF10K2-16

第二个模块没有响应,这似乎很奇怪。所以我把get_model_name_of循环到2,3,4,2,3,4,2,3,4....每隔一秒的读取尝试都以Error 110 while reading: Connection timed out结束。在行modbus_set_slave(modbus, slave);之后我添加了

代码语言:javascript
复制
usleep(0.005 * 1000000);

然后我就再也没有暂停了。我看了两遍手册页,没有发现任何关于这一点的警告。我也在谷歌上搜索,但我找到的“相似”帖子都没有任何帮助。

处理多个从属的最好方法是什么?为什么在这里增加半毫秒的睡眠会有帮助呢?我的意思是libmodus上的代码

代码语言:javascript
复制
static int _modbus_set_slave(modbus_t *ctx, int slave)
{
    /* Broadcast address is 0 (MODBUS_BROADCAST_ADDRESS) */
    if (slave >= 0 && slave <= 247) {
        ctx->slave = slave;
    } else {
        errno = EINVAL;
        return -1;
    }

    return 0;
}

在上下文中设置内部值。在更改上下文中的内部值和读取/写入总线之间是否存在时间限制?如果是这样,我应该在set_slave之后等待多长时间?为什么libmodbus要全局设置从属id,而不是像其他库(如pymodbus)那样将其作为read/write方法中的参数?

或者我只是不正确地使用了这个API?

谢谢

EN

回答 1

Stack Overflow用户

发布于 2018-10-02 09:09:33

我可能错了..。但是..。据我所知。modbus主机发出一个请求,目标是特定的从机号。其目的是接收来自目标从站的应答,然后向下一个从站发送请求,并等待来自第二个从站的应答。如果在没有等待第一个从站回复的情况下发出请求..则有可能错过来自第二个从设备(或第三个或任何数量的从设备)的应答,而第一个从设备应答正在由主设备发送和接收。

我不擅长C语言编程。但我建议你检查一下this..as,我想这可能是为什么你添加一个延迟似乎有帮助的原因。(还有..Modbus协议的一部分确实要求在信号传输中暂停以定义传输的开始和结束。)如果我是正确的,那么只有当您知道正在发送的数据的大小和计算response..For的时间时,使用延迟才能很好地工作。其他情况下,某种握手将是安全的。例如读取线圈..其指示数据是否被刷新并准备好作为可能的交通信号灯从从机读取。以控制去往其它从站的请求的时序,并避免响应的冲突。再一次..。我不擅长C语言,如果我曲解了程序..请忽略我所说的话。如果有帮助的话..我会很高兴听到的。

彼得

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34387820

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档