我是modbus的新手。我花了几个小时阅读帮助(?)文件,这似乎永远不会给你一个例子!我在Raspberry Pi,model3上使用C并安装了libmodbus。我试图通过FTDI USB转RS485转换器与epSolar太阳能电池板控制器交谈。 epSolar文档说,读取输入寄存器从地址3000开始并继续到311D。我想读3104。 我修改了下面的代码。它连接到设备但尝试读取输入寄存器0x04始终返回-1:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <modbus.h>
enum {TCP, RTU};
int main(int argc, char *argv[])
{
int socket;
modbus_t *ctx;
modbus_mapping_t *mb_mapping;
int rc;
int use_backend;
int i;
uint16_t tab_reg[64];
use_backend = RTU;
printf("Waiting for Serial connection\n");
ctx = modbus_new_rtu("/dev/SOLAR", 115200, 'N', 8, 1);
modbus_set_slave(ctx, 0);
//modbus_connect(ctx);
if(modbus_connect(ctx) == -1)
{
fprintf(stderr, "Serial connection failed:
%s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
printf("Serial connection started!\n");
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;
}
rc = modbus_read_input_registers(ctx, 1, 0x0A, tab_reg);
if(rc == -1)
{
fprintf(stderr, "%s\n", modbus_strerror(errno));
return -1;
}
for(i=0; i < rc; i++)
printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
modbus_mapping_free(mb_mapping);
modbus_free(ctx);
modbus_close(ctx);
return 0;
}
它连接正常并分配映射,但rc始终为-1,并显示端口已超时的错误消息。 我已经没有想法了,感觉我正在穿过糖浆!
最值得赞赏的任何帮助。
答案 0 :(得分:0)
我也是Modbus的新手。根据我目前的经验,确保为tab_reg
分配足够的内存来存储结果。同时尝试设置调试模式,即 modbus_set_debug(ctx, TRUE);
,以检查请求和响应代码。
答案 1 :(得分:0)
我知道这是一个非常老的问题,但是希望这个答案能对通过Google搜索登陆这里的人有所帮助。
我看到一些需要帮助的地方。
如上文Saad所述,上面的Modbus服务器ID不正确。 ID 0保留用于广播消息,从站不会响应。找出目标设备的Modbus ID是什么,然后使用它。
我认为,如果您提供的串行端口有效,那么您还将始终获得正确的“连接”,这是在困扰您。这不是到任何特定设备的连接,而是到Modbus网络端口的连接。您正在超时,因为libmodbus预期会收到响应,但网络上没有收到响应。
所提供的代码中还有其他一些小麻烦,但是鉴于这篇文章的年代,我几乎觉得我在挑剔OP可能已经解决的问题。最大的问题是无法使用的从站ID。其他小问题包括:不必要地使用了modbus_mapping(用于服务器/从属服务器的结构),可能对modbus_mapping进行了错误分配(没有为输入寄存器分配空间)。