Commit bf6718c9b1364624f2f41dec96a1814a3856b619
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.
Showing
3 changed files
with
76 additions
and
1 deletions
src/modbus-rtu-private.h
| @@ -80,7 +80,12 @@ typedef struct _modbus_rtu { | @@ -80,7 +80,12 @@ typedef struct _modbus_rtu { | ||
| 80 | #endif | 80 | #endif |
| 81 | #if HAVE_DECL_TIOCSRS485 | 81 | #if HAVE_DECL_TIOCSRS485 |
| 82 | int serial_mode; | 82 | int serial_mode; |
| 83 | + int usage_rts; | ||
| 83 | #endif | 84 | #endif |
| 84 | } modbus_rtu_t; | 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 | #endif /* _MODBUS_RTU_PRIVATE_H_ */ | 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,7 +264,21 @@ ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_length) | ||
| 264 | DWORD n_bytes = 0; | 264 | DWORD n_bytes = 0; |
| 265 | return (WriteFile(ctx_rtu->w_ser.fd, req, req_length, &n_bytes, NULL)) ? n_bytes : -1; | 265 | return (WriteFile(ctx_rtu->w_ser.fd, req, req_length, &n_bytes, NULL)) ? n_bytes : -1; |
| 266 | #else | 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 | #endif | 282 | #endif |
| 269 | } | 283 | } |
| 270 | 284 | ||
| @@ -703,6 +717,10 @@ static int _modbus_rtu_connect(modbus_t *ctx) | @@ -703,6 +717,10 @@ static int _modbus_rtu_connect(modbus_t *ctx) | ||
| 703 | #if HAVE_DECL_TIOCSRS485 | 717 | #if HAVE_DECL_TIOCSRS485 |
| 704 | /* The RS232 mode has been set by default */ | 718 | /* The RS232 mode has been set by default */ |
| 705 | ctx_rtu->serial_mode = MODBUS_RTU_RS232; | 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 | #endif | 724 | #endif |
| 707 | 725 | ||
| 708 | return 0; | 726 | return 0; |
| @@ -764,6 +782,38 @@ int modbus_rtu_get_serial_mode(modbus_t *ctx) { | @@ -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 | void _modbus_rtu_close(modbus_t *ctx) | 817 | void _modbus_rtu_close(modbus_t *ctx) |
| 768 | { | 818 | { |
| 769 | /* Closes the file descriptor in RTU mode */ | 819 | /* Closes the file descriptor in RTU mode */ |
| @@ -915,3 +965,17 @@ modbus_t* modbus_new_rtu(const char *device, | @@ -915,3 +965,17 @@ modbus_t* modbus_new_rtu(const char *device, | ||
| 915 | 965 | ||
| 916 | return ctx; | 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,7 +32,13 @@ modbus_t* modbus_new_rtu(const char *device, int baud, char parity, | ||
| 32 | #define MODBUS_RTU_RS232 0 | 32 | #define MODBUS_RTU_RS232 0 |
| 33 | #define MODBUS_RTU_RS485 1 | 33 | #define MODBUS_RTU_RS485 1 |
| 34 | 34 | ||
| 35 | +#define MODBUS_NO_USE_RTS 0 | ||
| 36 | +#define MODBUS_USE_RTS 1 | ||
| 37 | + | ||
| 35 | int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode); | 38 | int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode); |
| 36 | int modbus_rtu_get_serial_mode(modbus_t *ctx); | 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 | #endif /* _MODBUS_RTU_H_ */ | 44 | #endif /* _MODBUS_RTU_H_ */ |