Commit cf22eabc2701cc9ddfd4a921ba7c6e0822db5d7a
Committed by
Stéphane Raimbault
1 parent
c7eb7b96
Implemented runtime configurable RTS delay
Showing
6 changed files
with
155 additions
and
7 deletions
doc/Makefile.am
| @@ -29,6 +29,8 @@ TXT3 = \ | @@ -29,6 +29,8 @@ TXT3 = \ | ||
| 29 | modbus_rtu_set_serial_mode.txt \ | 29 | modbus_rtu_set_serial_mode.txt \ |
| 30 | modbus_rtu_get_rts.txt \ | 30 | modbus_rtu_get_rts.txt \ |
| 31 | modbus_rtu_set_rts.txt \ | 31 | modbus_rtu_set_rts.txt \ |
| 32 | + modbus_rtu_get_rts_delay.txt \ | ||
| 33 | + modbus_rtu_set_rts_delay.txt \ | ||
| 32 | modbus_rtu_set_custom_rts.txt \ | 34 | modbus_rtu_set_custom_rts.txt \ |
| 33 | modbus_send_raw_request.txt \ | 35 | modbus_send_raw_request.txt \ |
| 34 | modbus_set_bits_from_bytes.txt \ | 36 | modbus_set_bits_from_bytes.txt \ |
doc/modbus_rtu_get_rts_delay.txt
0 → 100644
| 1 | +modbus_rtu_get_rts_delay(3) | ||
| 2 | +=========================== | ||
| 3 | + | ||
| 4 | + | ||
| 5 | +NAME | ||
| 6 | +---- | ||
| 7 | +modbus_rtu_get_rts_delay - get the current RTS delay in RTU | ||
| 8 | + | ||
| 9 | + | ||
| 10 | +SYNOPSIS | ||
| 11 | +-------- | ||
| 12 | +*int modbus_rtu_get_rts_delay(modbus_t *'ctx');* | ||
| 13 | + | ||
| 14 | + | ||
| 15 | +DESCRIPTION | ||
| 16 | +----------- | ||
| 17 | + | ||
| 18 | +The _modbus_rtu_get_rts_delay()_ function shall get the current Request To Send | ||
| 19 | +delay period of the libmodbus context 'ctx'. | ||
| 20 | + | ||
| 21 | +This function can only be used with a context using a RTU backend. | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +RETURN VALUE | ||
| 25 | +------------ | ||
| 26 | +The _modbus_rtu_get_rts_delay()_ function shall return the current RTS delay in | ||
| 27 | +microseconds if successful. Otherwise it shall return -1 and set errno. | ||
| 28 | + | ||
| 29 | + | ||
| 30 | +ERRORS | ||
| 31 | +------ | ||
| 32 | +*EINVAL*:: | ||
| 33 | +The libmodbus backend is not RTU. | ||
| 34 | + | ||
| 35 | + | ||
| 36 | +SEE ALSO | ||
| 37 | +-------- | ||
| 38 | +linkmb:modbus_rtu_set_rts_delay[3] | ||
| 39 | + | ||
| 40 | + | ||
| 41 | +AUTHORS | ||
| 42 | +------- | ||
| 43 | +Jimmy Bergström <jimmy@ekontroll.com> | ||
| 44 | + | ||
| 45 | +The libmodbus documentation was written by Stéphane Raimbault | ||
| 46 | +<stephane.raimbault@gmail.com> |
doc/modbus_rtu_set_rts_delay.txt
0 → 100644
| 1 | +modbus_rtu_set_rts_delay(3) | ||
| 2 | +=========================== | ||
| 3 | + | ||
| 4 | + | ||
| 5 | +NAME | ||
| 6 | +---- | ||
| 7 | +modbus_rtu_set_rts_delay - set the RTS delay in RTU | ||
| 8 | + | ||
| 9 | + | ||
| 10 | +SYNOPSIS | ||
| 11 | +-------- | ||
| 12 | +*int modbus_rtu_set_rts_delay(modbus_t *'ctx', int 'us');* | ||
| 13 | + | ||
| 14 | + | ||
| 15 | +DESCRIPTION | ||
| 16 | +----------- | ||
| 17 | + | ||
| 18 | +The _modbus_rtu_set_rts_delay()_ function shall set the Request To Send delay | ||
| 19 | +period of the libmodbus context 'ctx'. | ||
| 20 | + | ||
| 21 | +This function can only be used with a context using a RTU backend. | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +RETURN VALUE | ||
| 25 | +------------ | ||
| 26 | +The _modbus_rtu_set_rts_delay()_ function shall return 0 if successful. | ||
| 27 | +Otherwise it shall return -1 and set errno. | ||
| 28 | + | ||
| 29 | + | ||
| 30 | +ERRORS | ||
| 31 | +------ | ||
| 32 | +*EINVAL*:: | ||
| 33 | +The libmodbus backend is not RTU or a negative delay was specified. | ||
| 34 | + | ||
| 35 | + | ||
| 36 | +SEE ALSO | ||
| 37 | +-------- | ||
| 38 | +linkmb:modbus_rtu_get_rts_delay[3] | ||
| 39 | + | ||
| 40 | + | ||
| 41 | +AUTHORS | ||
| 42 | +------- | ||
| 43 | +Jimmy Bergström <jimmy@ekontroll.com> | ||
| 44 | + | ||
| 45 | +The libmodbus documentation was written by Stéphane Raimbault | ||
| 46 | +<stephane.raimbault@gmail.com> |
src/modbus-rtu-private.h
| @@ -25,10 +25,6 @@ | @@ -25,10 +25,6 @@ | ||
| 25 | 25 | ||
| 26 | #define _MODBUS_RTU_CHECKSUM_LENGTH 2 | 26 | #define _MODBUS_RTU_CHECKSUM_LENGTH 2 |
| 27 | 27 | ||
| 28 | -/* Time waited beetween the RTS switch before transmit data or after transmit | ||
| 29 | - data before to read (1 ms) */ | ||
| 30 | -#define _MODBUS_RTU_TIME_BETWEEN_RTS_SWITCH 1000 | ||
| 31 | - | ||
| 32 | #if defined(_WIN32) | 28 | #if defined(_WIN32) |
| 33 | #if !defined(ENOTSUP) | 29 | #if !defined(ENOTSUP) |
| 34 | #define ENOTSUP WSAEOPNOTSUPP | 30 | #define ENOTSUP WSAEOPNOTSUPP |
| @@ -69,6 +65,7 @@ typedef struct _modbus_rtu { | @@ -69,6 +65,7 @@ typedef struct _modbus_rtu { | ||
| 69 | #endif | 65 | #endif |
| 70 | #if HAVE_DECL_TIOCM_RTS | 66 | #if HAVE_DECL_TIOCM_RTS |
| 71 | int rts; | 67 | int rts; |
| 68 | + int rts_delay; | ||
| 72 | int onebyte_time; | 69 | int onebyte_time; |
| 73 | void (*set_rts) (modbus_t *ctx, int on); | 70 | void (*set_rts) (modbus_t *ctx, int on); |
| 74 | #endif | 71 | #endif |
src/modbus-rtu.c
| @@ -284,11 +284,11 @@ static ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_lengt | @@ -284,11 +284,11 @@ static ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_lengt | ||
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | ctx_rtu->set_rts(ctx, ctx_rtu->rts == MODBUS_RTU_RTS_UP); | 286 | ctx_rtu->set_rts(ctx, ctx_rtu->rts == MODBUS_RTU_RTS_UP); |
| 287 | - usleep(_MODBUS_RTU_TIME_BETWEEN_RTS_SWITCH); | 287 | + usleep(ctx_rtu->rts_delay); |
| 288 | 288 | ||
| 289 | size = write(ctx->s, req, req_length); | 289 | size = write(ctx->s, req, req_length); |
| 290 | 290 | ||
| 291 | - usleep(ctx_rtu->onebyte_time * req_length + _MODBUS_RTU_TIME_BETWEEN_RTS_SWITCH); | 291 | + usleep(ctx_rtu->onebyte_time * req_length + ctx_rtu->rts_delay); |
| 292 | ctx_rtu->set_rts(ctx, ctx_rtu->rts != MODBUS_RTU_RTS_UP); | 292 | ctx_rtu->set_rts(ctx, ctx_rtu->rts != MODBUS_RTU_RTS_UP); |
| 293 | 293 | ||
| 294 | return size; | 294 | return size; |
| @@ -1028,6 +1028,57 @@ int modbus_rtu_get_rts(modbus_t *ctx) | @@ -1028,6 +1028,57 @@ int modbus_rtu_get_rts(modbus_t *ctx) | ||
| 1028 | } | 1028 | } |
| 1029 | } | 1029 | } |
| 1030 | 1030 | ||
| 1031 | +int modbus_rtu_set_rts_delay(modbus_t *ctx, int us) | ||
| 1032 | +{ | ||
| 1033 | + if (ctx == NULL || us < 0) { | ||
| 1034 | + errno = EINVAL; | ||
| 1035 | + return -1; | ||
| 1036 | + } | ||
| 1037 | + | ||
| 1038 | + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { | ||
| 1039 | +#if HAVE_DECL_TIOCM_RTS | ||
| 1040 | + modbus_rtu_t *ctx_rtu; | ||
| 1041 | + ctx_rtu = (modbus_rtu_t *)ctx->backend_data; | ||
| 1042 | + ctx_rtu->rts_delay = us; | ||
| 1043 | + return 0; | ||
| 1044 | +#else | ||
| 1045 | + if (ctx->debug) { | ||
| 1046 | + fprintf(stderr, "This function isn't supported on your platform\n"); | ||
| 1047 | + } | ||
| 1048 | + errno = ENOTSUP; | ||
| 1049 | + return -1; | ||
| 1050 | +#endif | ||
| 1051 | + } else { | ||
| 1052 | + errno = EINVAL; | ||
| 1053 | + return -1; | ||
| 1054 | + } | ||
| 1055 | +} | ||
| 1056 | + | ||
| 1057 | +int modbus_rtu_get_rts_delay(modbus_t *ctx) | ||
| 1058 | +{ | ||
| 1059 | + if (ctx == NULL) { | ||
| 1060 | + errno = EINVAL; | ||
| 1061 | + return -1; | ||
| 1062 | + } | ||
| 1063 | + | ||
| 1064 | + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { | ||
| 1065 | +#if HAVE_DECL_TIOCM_RTS | ||
| 1066 | + modbus_rtu_t *ctx_rtu; | ||
| 1067 | + ctx_rtu = (modbus_rtu_t *)ctx->backend_data; | ||
| 1068 | + return ctx_rtu->rts_delay; | ||
| 1069 | +#else | ||
| 1070 | + if (ctx->debug) { | ||
| 1071 | + fprintf(stderr, "This function isn't supported on your platform\n"); | ||
| 1072 | + } | ||
| 1073 | + errno = ENOTSUP; | ||
| 1074 | + return -1; | ||
| 1075 | +#endif | ||
| 1076 | + } else { | ||
| 1077 | + errno = EINVAL; | ||
| 1078 | + return -1; | ||
| 1079 | + } | ||
| 1080 | +} | ||
| 1081 | + | ||
| 1031 | int modbus_rtu_set_custom_rts(modbus_t *ctx, void (*set_rts) (modbus_t *ctx, int on)) | 1082 | int modbus_rtu_set_custom_rts(modbus_t *ctx, void (*set_rts) (modbus_t *ctx, int on)) |
| 1032 | { | 1083 | { |
| 1033 | if (ctx == NULL) { | 1084 | if (ctx == NULL) { |
| @@ -1209,9 +1260,12 @@ modbus_t* modbus_new_rtu(const char *device, | @@ -1209,9 +1260,12 @@ modbus_t* modbus_new_rtu(const char *device, | ||
| 1209 | ctx_rtu->rts = MODBUS_RTU_RTS_NONE; | 1260 | ctx_rtu->rts = MODBUS_RTU_RTS_NONE; |
| 1210 | 1261 | ||
| 1211 | /* Calculate estimated time in micro second to send one byte */ | 1262 | /* Calculate estimated time in micro second to send one byte */ |
| 1212 | - ctx_rtu->onebyte_time = (1000 * 1000) * (1 + data_bit + (parity == 'N' ? 0 : 1) + stop_bit) / baud; | 1263 | + ctx_rtu->onebyte_time = 1000000 * (1 + data_bit + (parity == 'N' ? 0 : 1) + stop_bit) / baud; |
| 1213 | 1264 | ||
| 1214 | ctx_rtu->set_rts = _modbus_rtu_ioctl_rts; | 1265 | ctx_rtu->set_rts = _modbus_rtu_ioctl_rts; |
| 1266 | + | ||
| 1267 | + /* The delay before and after transmission when toggling the RTS pin */ | ||
| 1268 | + ctx_rtu->rts_delay = ctx_rtu->onebyte_time; | ||
| 1215 | #endif | 1269 | #endif |
| 1216 | 1270 | ||
| 1217 | ctx_rtu->confirmation_to_ignore = FALSE; | 1271 | ctx_rtu->confirmation_to_ignore = FALSE; |
src/modbus-rtu.h
| @@ -33,6 +33,9 @@ MODBUS_API int modbus_rtu_set_rts(modbus_t *ctx, int mode); | @@ -33,6 +33,9 @@ MODBUS_API int modbus_rtu_set_rts(modbus_t *ctx, int mode); | ||
| 33 | MODBUS_API int modbus_rtu_get_rts(modbus_t *ctx); | 33 | MODBUS_API int modbus_rtu_get_rts(modbus_t *ctx); |
| 34 | MODBUS_API int modbus_rtu_set_custom_rts(modbus_t *ctx, void (*set_rts) (modbus_t *ctx, int on)); | 34 | MODBUS_API int modbus_rtu_set_custom_rts(modbus_t *ctx, void (*set_rts) (modbus_t *ctx, int on)); |
| 35 | 35 | ||
| 36 | +MODBUS_API int modbus_rtu_set_rts_delay(modbus_t *ctx, int us); | ||
| 37 | +MODBUS_API int modbus_rtu_get_rts_delay(modbus_t *ctx); | ||
| 38 | + | ||
| 36 | MODBUS_END_DECLS | 39 | MODBUS_END_DECLS |
| 37 | 40 | ||
| 38 | #endif /* MODBUS_RTU_H */ | 41 | #endif /* MODBUS_RTU_H */ |