Commit bf6718c9b1364624f2f41dec96a1814a3856b619

Authored by Torello Querci
Committed by Stéphane Raimbault
1 parent 2f911c3b

Add the support to RTS signal in order to have RS485 working on some linux box with RS485 on-board.

src/modbus-rtu-private.h
... ... @@ -80,7 +80,12 @@ typedef struct _modbus_rtu {
80 80 #endif
81 81 #if HAVE_DECL_TIOCSRS485
82 82 int serial_mode;
  83 + int usage_rts;
83 84 #endif
84 85 } modbus_rtu_t;
85 86  
  87 +/* Time waited beetween the RTS switch before transmit data o after transmit data before to read */
  88 +#define TIME_BETWEEN_RTS_SWITCH 10000
  89 +void _modbus_rtu_setrts(int fd, int on);
  90 +
86 91 #endif /* _MODBUS_RTU_PRIVATE_H_ */
... ...
src/modbus-rtu.c
... ... @@ -264,7 +264,21 @@ ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_length)
264 264 DWORD n_bytes = 0;
265 265 return (WriteFile(ctx_rtu->w_ser.fd, req, req_length, &n_bytes, NULL)) ? n_bytes : -1;
266 266 #else
267   - return write(ctx->s, req, req_length);
  267 + modbus_rtu_t *ctx_rtu = ctx->backend_data;
  268 + if (ctx_rtu->usage_rts == MODBUS_USE_RTS) {
  269 + ssize_t size;
  270 +
  271 + _modbus_rtu_setrts(ctx->s,1);
  272 + usleep(TIME_BETWEEN_RTS_SWITCH);
  273 +
  274 + size = write(ctx->s, req, req_length);
  275 + usleep(TIME_BETWEEN_RTS_SWITCH);
  276 + _modbus_rtu_setrts(ctx->s,0);
  277 +
  278 + return size;
  279 + } else {
  280 + return write(ctx->s, req, req_length);
  281 + }
268 282 #endif
269 283 }
270 284  
... ... @@ -703,6 +717,10 @@ static int _modbus_rtu_connect(modbus_t *ctx)
703 717 #if HAVE_DECL_TIOCSRS485
704 718 /* The RS232 mode has been set by default */
705 719 ctx_rtu->serial_mode = MODBUS_RTU_RS232;
  720 +
  721 + /* The RTS usage has been set by default */
  722 + ctx_rtu->usage_rts = MODBUS_NO_USE_RTS;
  723 +
706 724 #endif
707 725  
708 726 return 0;
... ... @@ -764,6 +782,38 @@ int modbus_rtu_get_serial_mode(modbus_t *ctx) {
764 782 }
765 783 }
766 784  
  785 +int modbus_rtu_set_usage_rts(modbus_t *ctx, int mode)
  786 +{
  787 + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) {
  788 + modbus_rtu_t *ctx_rtu = ctx->backend_data;
  789 +
  790 + if (mode == MODBUS_NO_USE_RTS || mode == MODBUS_USE_RTS ) {
  791 + ctx_rtu->usage_rts = mode;
  792 + return 0;
  793 + }
  794 +
  795 + if (ctx->debug) {
  796 + fprintf(stderr, "This function isn't supported on your platform\n");
  797 + }
  798 + errno = ENOTSUP;
  799 + return -1;
  800 + }
  801 +
  802 + /* Wrong backend and invalid mode specified */
  803 + errno = EINVAL;
  804 + return -1;
  805 +}
  806 +
  807 +int modbus_rtu_get_usage_rts(modbus_t *ctx) {
  808 + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) {
  809 + modbus_rtu_t *ctx_rtu = ctx->backend_data;
  810 + return ctx_rtu->usage_rts;
  811 + } else {
  812 + errno = EINVAL;
  813 + return -1;
  814 + }
  815 +}
  816 +
767 817 void _modbus_rtu_close(modbus_t *ctx)
768 818 {
769 819 /* Closes the file descriptor in RTU mode */
... ... @@ -915,3 +965,17 @@ modbus_t* modbus_new_rtu(const char *device,
915 965  
916 966 return ctx;
917 967 }
  968 +
  969 +void _modbus_rtu_setrts(int fd, int on)
  970 +{
  971 + int controlbits;
  972 +
  973 + ioctl(fd, TIOCMGET, &controlbits);
  974 + if (on) {
  975 + controlbits |= TIOCM_RTS;
  976 + } else {
  977 + controlbits &= ~TIOCM_RTS;
  978 + }
  979 + ioctl(fd, TIOCMSET, &controlbits);
  980 +}
  981 +
... ...
src/modbus-rtu.h
... ... @@ -32,7 +32,13 @@ modbus_t* modbus_new_rtu(const char *device, int baud, char parity,
32 32 #define MODBUS_RTU_RS232 0
33 33 #define MODBUS_RTU_RS485 1
34 34  
  35 +#define MODBUS_NO_USE_RTS 0
  36 +#define MODBUS_USE_RTS 1
  37 +
35 38 int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode);
36 39 int modbus_rtu_get_serial_mode(modbus_t *ctx);
37 40  
  41 +int modbus_rtu_set_usage_rts(modbus_t *ctx, int mode);
  42 +int modbus_rtu_get_usage_rts(modbus_t *ctx);
  43 +
38 44 #endif /* _MODBUS_RTU_H_ */
... ...