libmodbus 的链接网址
关于 rtu 功能,libmodbus 库的相关 API 如下:
测试代码的网址链接
测试代码如下:
modbus_t *ctx;
uint16_t tab_reg[10];
ctx = modbus_new_rtu("/dev/ttyS0", 115200, 'N', 8, 1);
modbus_set_slave(ctx, 1);
modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485);
modbus_rtu_set_rts(ctx, MODBUS_RTU_RTS_UP);
if (modbus_connect(ctx) == -1) {
fprintf(stderr, "Connexion failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
rc = modbus_read_registers(ctx, 0, 7, tab_reg);
if (rc == -1) {
fprintf(stderr, "%s\n", modbus_strerror(errno));
return -1;
}
modbus_close(ctx);
modbus_free(ctx);
按照上面代码,测试通过 rs485 获取 modbus 数据是有问题的。
问题1
modbus_rtu_set_serial_mode 函数涉及到了串口操作
如果在未连接前,ctx->s 的值是有问题的。此时会报错。
将此函数放在 connect 后面即可。
问题2
报错提示
MODBUS RTU Error Connection Time Out: select
官方默认的 rts 操作函数如下
需要使用设置函数
int modbus_rtu_set_custom_rts(modbus_t *ctx, void (*set_rts) (modbus_t *ctx, int on))
调用自己的 rts 相关函数。
修改代码如下:
if (modbus_connect(ctx) == -1)
{
fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
modbus_set_debug(ctx,TRUE);
if (modbus_connect(ctx) == -1)
{
fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
if (modbus_rtu_set_serial_mode(ctx,MODBUS_RTU_RS485) == -1)
{
fprintf(stderr, "set rs485 mod failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
if(modbus_rtu_set_rts(ctx,MODBUS_RTU_RTS_UP ) == -1)
{
fprintf(stderr, "set rs485 rts up failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
// if(modbus_rtu_set_rts_delay(ctx,15000 ) == -1)
// {
// fprintf(stderr, "set rs485 rts delay us failed: %s\n", modbus_strerror(errno));
// modbus_free(ctx);
// return -1;
// }
if(modbus_rtu_set_custom_rts(ctx, custom_rts_rtu) == -1)
{
fprintf(stderr, "set custom rts fun failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
自定义的rts功能相关函数
#include <fcntl.h>
#define SERVER_GPIO_INDEX "110"
// static int custom_rts_ioctl_init(void)
// {
// int fd;
// //index config
// fd = open("/sys/class/gpio/export", O_WRONLY);
// if(fd < 0)
// return 1;
// write(fd, SERVER_GPIO_INDEX, strlen(SERVER_GPIO_INDEX));
// close(fd);
// //direction config
// fd = open("/sys/class/gpio/gpio" SERVER_GPIO_INDEX "/direction", O_WRONLY);
// if(fd < 0)
// return 2;
// write(fd, "out", strlen("out"));
// close(fd);
// return 0;
// }
static int custom_rts_rtu_ioctl_on(void)
{
int fd;
fd = open("/sys/class/gpio/gpio" SERVER_GPIO_INDEX "/value", O_WRONLY);
if(fd < 0)
return 1;
write(fd, "1", 1);
close(fd);
return 0;
}
static int custom_rts_rtu_ioctl_off(void)
{
int fd;
fd = open("/sys/class/gpio/gpio" SERVER_GPIO_INDEX "/value", O_WRONLY);
if(fd < 0)
return 1;
write(fd, "0", 1);
close(fd);
return 0;
}
static void custom_rts_rtu(modbus_t *ctx, int on)
{
if (on)
{
custom_rts_rtu_ioctl_on();
}
else
{
custom_rts_rtu_ioctl_off();
}
}
重新编译,下载即可。最终测试,模拟软件的log日志可以看到通信信息,如下: