diff --git a/src/modbus-rtu-private.h b/src/modbus-rtu-private.h index 2948f17..2843325 100644 --- a/src/modbus-rtu-private.h +++ b/src/modbus-rtu-private.h @@ -80,7 +80,12 @@ typedef struct _modbus_rtu { #endif #if HAVE_DECL_TIOCSRS485 int serial_mode; + int usage_rts; #endif } modbus_rtu_t; +/* Time waited beetween the RTS switch before transmit data o after transmit data before to read */ +#define TIME_BETWEEN_RTS_SWITCH 10000 +void _modbus_rtu_setrts(int fd, int on); + #endif /* _MODBUS_RTU_PRIVATE_H_ */ diff --git a/src/modbus-rtu.c b/src/modbus-rtu.c index bc2118e..a01b98d 100644 --- a/src/modbus-rtu.c +++ b/src/modbus-rtu.c @@ -264,7 +264,21 @@ ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_length) DWORD n_bytes = 0; return (WriteFile(ctx_rtu->w_ser.fd, req, req_length, &n_bytes, NULL)) ? n_bytes : -1; #else - return write(ctx->s, req, req_length); + modbus_rtu_t *ctx_rtu = ctx->backend_data; + if (ctx_rtu->usage_rts == MODBUS_USE_RTS) { + ssize_t size; + + _modbus_rtu_setrts(ctx->s,1); + usleep(TIME_BETWEEN_RTS_SWITCH); + + size = write(ctx->s, req, req_length); + usleep(TIME_BETWEEN_RTS_SWITCH); + _modbus_rtu_setrts(ctx->s,0); + + return size; + } else { + return write(ctx->s, req, req_length); + } #endif } @@ -703,6 +717,10 @@ static int _modbus_rtu_connect(modbus_t *ctx) #if HAVE_DECL_TIOCSRS485 /* The RS232 mode has been set by default */ ctx_rtu->serial_mode = MODBUS_RTU_RS232; + + /* The RTS usage has been set by default */ + ctx_rtu->usage_rts = MODBUS_NO_USE_RTS; + #endif return 0; @@ -764,6 +782,38 @@ int modbus_rtu_get_serial_mode(modbus_t *ctx) { } } +int modbus_rtu_set_usage_rts(modbus_t *ctx, int mode) +{ + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { + modbus_rtu_t *ctx_rtu = ctx->backend_data; + + if (mode == MODBUS_NO_USE_RTS || mode == MODBUS_USE_RTS ) { + ctx_rtu->usage_rts = mode; + return 0; + } + + if (ctx->debug) { + fprintf(stderr, "This function isn't supported on your platform\n"); + } + errno = ENOTSUP; + return -1; + } + + /* Wrong backend and invalid mode specified */ + errno = EINVAL; + return -1; +} + +int modbus_rtu_get_usage_rts(modbus_t *ctx) { + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { + modbus_rtu_t *ctx_rtu = ctx->backend_data; + return ctx_rtu->usage_rts; + } else { + errno = EINVAL; + return -1; + } +} + void _modbus_rtu_close(modbus_t *ctx) { /* Closes the file descriptor in RTU mode */ @@ -915,3 +965,17 @@ modbus_t* modbus_new_rtu(const char *device, return ctx; } + +void _modbus_rtu_setrts(int fd, int on) +{ + int controlbits; + + ioctl(fd, TIOCMGET, &controlbits); + if (on) { + controlbits |= TIOCM_RTS; + } else { + controlbits &= ~TIOCM_RTS; + } + ioctl(fd, TIOCMSET, &controlbits); +} + diff --git a/src/modbus-rtu.h b/src/modbus-rtu.h index 4ec55d3..497b456 100644 --- a/src/modbus-rtu.h +++ b/src/modbus-rtu.h @@ -32,7 +32,13 @@ modbus_t* modbus_new_rtu(const char *device, int baud, char parity, #define MODBUS_RTU_RS232 0 #define MODBUS_RTU_RS485 1 +#define MODBUS_NO_USE_RTS 0 +#define MODBUS_USE_RTS 1 + int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode); int modbus_rtu_get_serial_mode(modbus_t *ctx); +int modbus_rtu_set_usage_rts(modbus_t *ctx, int mode); +int modbus_rtu_get_usage_rts(modbus_t *ctx); + #endif /* _MODBUS_RTU_H_ */