如何使用 libmodbus 从 modbus/tcp 中读取
How to read from modbus/tcp using libmodbus
我有一个 moxa ioLogik E1214,我想使用 modbus/tcp 与其通信。我找到了一个应该这样做的图书馆 - libmodbus。首先,我从他们的网站上复制了代码示例并稍作修改,使其看起来像这样:
#include <stdio.h>
#ifndef _MSC_VER
#include <unistd.h>
#include <sys/time.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <modbus.h>
#define G_MSEC_PER_SEC 1000
int main(int argc, char *argv[])
{
modbus_t *mb;
uint16_t tab_reg[30];
int length = 6;
mb = modbus_new_tcp("192.168.127.254", 502);
if (modbus_connect(mb) == -1) {
fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
modbus_free(mb);
return -1;
}
/* Read "length" registers from the address 0 */
int read_val = modbus_read_registers(mb, 0, length, tab_reg);
if(read_val==-1)
printf("ERROR: %s\n", modbus_strerror(errno));
else
{
printf("Read registers: %d\n", read_val);
for(int i=0; i<length; i++)
{
printf("%d ", tab_reg[i]);
}
printf("\n");
}
modbus_close(mb);
modbus_free(mb);
return 0;
}
连接正常,但我在读取寄存器时遇到问题。在文档中有一些带有描述、起始地址、长度等的参数,它看起来像这样:
所以我理解使用int read_val = modbus_read_registers(mb, 0, length, tab_reg);
应该从地址0读取一个值并存储在tab_reg中。但我收到错误“非法数据地址”。我尝试阅读的其他地址也是如此。
所以,总而言之 - 我是否理解正确?我应该如何使用 libmodbus 来实际读取寄存器?
您的从站似乎在地址 0 处没有任何保持寄存器,因此它抱怨 illegal data address
错误。
您需要查看您拥有的 Modbus 寄存器映射,并相应地使用 libmodbus 中的正确 Modbus 函数。例如,如果你想读取你的变量 RLY_pulseOnWidth
你必须使用:
int read_val = modbus_read_input_registers(mb, 52, length, tab_reg);
但要阅读RLY_TotalCount
:
int read_val = modbus_read_registers(mb, 64, length, tab_reg);
您可以在此处查看与您的 "Point Type" 列相关的所有 Modbus 功能代码:
https://github.com/stephane/libmodbus/blob/ddac0cf909d9ab05423df7b9a66e6e60e8bb0fbb/src/modbus.h
您正在尝试使用 "read registers"(int16 值),而您想要的是 "read coil"(位)。线圈和寄存器存储在单独的表中,因此寻址不同。
使用 modbus_read_bits 读出 RLY_status,因为正如您的文档所述,它是一个线圈值。
您需要以不同于线圈的方式读取输入和保持寄存器。您的示例代码应该适合读取保持寄存器。
我有一个 moxa ioLogik E1214,我想使用 modbus/tcp 与其通信。我找到了一个应该这样做的图书馆 - libmodbus。首先,我从他们的网站上复制了代码示例并稍作修改,使其看起来像这样:
#include <stdio.h>
#ifndef _MSC_VER
#include <unistd.h>
#include <sys/time.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <modbus.h>
#define G_MSEC_PER_SEC 1000
int main(int argc, char *argv[])
{
modbus_t *mb;
uint16_t tab_reg[30];
int length = 6;
mb = modbus_new_tcp("192.168.127.254", 502);
if (modbus_connect(mb) == -1) {
fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
modbus_free(mb);
return -1;
}
/* Read "length" registers from the address 0 */
int read_val = modbus_read_registers(mb, 0, length, tab_reg);
if(read_val==-1)
printf("ERROR: %s\n", modbus_strerror(errno));
else
{
printf("Read registers: %d\n", read_val);
for(int i=0; i<length; i++)
{
printf("%d ", tab_reg[i]);
}
printf("\n");
}
modbus_close(mb);
modbus_free(mb);
return 0;
}
连接正常,但我在读取寄存器时遇到问题。在文档中有一些带有描述、起始地址、长度等的参数,它看起来像这样:
所以我理解使用int read_val = modbus_read_registers(mb, 0, length, tab_reg);
应该从地址0读取一个值并存储在tab_reg中。但我收到错误“非法数据地址”。我尝试阅读的其他地址也是如此。
所以,总而言之 - 我是否理解正确?我应该如何使用 libmodbus 来实际读取寄存器?
您的从站似乎在地址 0 处没有任何保持寄存器,因此它抱怨 illegal data address
错误。
您需要查看您拥有的 Modbus 寄存器映射,并相应地使用 libmodbus 中的正确 Modbus 函数。例如,如果你想读取你的变量 RLY_pulseOnWidth
你必须使用:
int read_val = modbus_read_input_registers(mb, 52, length, tab_reg);
但要阅读RLY_TotalCount
:
int read_val = modbus_read_registers(mb, 64, length, tab_reg);
您可以在此处查看与您的 "Point Type" 列相关的所有 Modbus 功能代码:
https://github.com/stephane/libmodbus/blob/ddac0cf909d9ab05423df7b9a66e6e60e8bb0fbb/src/modbus.h
您正在尝试使用 "read registers"(int16 值),而您想要的是 "read coil"(位)。线圈和寄存器存储在单独的表中,因此寻址不同。
使用 modbus_read_bits 读出 RLY_status,因为正如您的文档所述,它是一个线圈值。
您需要以不同于线圈的方式读取输入和保持寄存器。您的示例代码应该适合读取保持寄存器。