Эх сурвалжийг харах

Implemented runtime configurable RTS delay

Jimmy Bergström 11 жил өмнө
parent
commit
cf22eabc27

+ 2 - 0
doc/Makefile.am

@@ -29,6 +29,8 @@ TXT3 = \
         modbus_rtu_set_serial_mode.txt \
         modbus_rtu_get_rts.txt \
         modbus_rtu_set_rts.txt \
+        modbus_rtu_get_rts_delay.txt \
+        modbus_rtu_set_rts_delay.txt \
         modbus_rtu_set_custom_rts.txt \
         modbus_send_raw_request.txt \
         modbus_set_bits_from_bytes.txt \

+ 46 - 0
doc/modbus_rtu_get_rts_delay.txt

@@ -0,0 +1,46 @@
+modbus_rtu_get_rts_delay(3)
+===========================
+
+
+NAME
+----
+modbus_rtu_get_rts_delay - get the current RTS delay in RTU
+
+
+SYNOPSIS
+--------
+*int modbus_rtu_get_rts_delay(modbus_t *'ctx');*
+
+
+DESCRIPTION
+-----------
+
+The _modbus_rtu_get_rts_delay()_ function shall get the current Request To Send
+delay period of the libmodbus context 'ctx'.
+
+This function can only be used with a context using a RTU backend.
+
+
+RETURN VALUE
+------------
+The _modbus_rtu_get_rts_delay()_ function shall return the current RTS delay in
+microseconds if successful. Otherwise it shall return -1 and set errno.
+
+
+ERRORS
+------
+*EINVAL*::
+The libmodbus backend is not RTU.
+
+
+SEE ALSO
+--------
+linkmb:modbus_rtu_set_rts_delay[3]
+
+
+AUTHORS
+-------
+Jimmy Bergström <jimmy@ekontroll.com>
+
+The libmodbus documentation was written by Stéphane Raimbault
+<stephane.raimbault@gmail.com>

+ 46 - 0
doc/modbus_rtu_set_rts_delay.txt

@@ -0,0 +1,46 @@
+modbus_rtu_set_rts_delay(3)
+===========================
+
+
+NAME
+----
+modbus_rtu_set_rts_delay - set the RTS delay in RTU
+
+
+SYNOPSIS
+--------
+*int modbus_rtu_set_rts_delay(modbus_t *'ctx', int 'us');*
+
+
+DESCRIPTION
+-----------
+
+The _modbus_rtu_set_rts_delay()_ function shall set the Request To Send delay
+period of the libmodbus context 'ctx'.
+
+This function can only be used with a context using a RTU backend.
+
+
+RETURN VALUE
+------------
+The _modbus_rtu_set_rts_delay()_ function shall return 0 if successful.
+Otherwise it shall return -1 and set errno.
+
+
+ERRORS
+------
+*EINVAL*::
+The libmodbus backend is not RTU or a negative delay was specified.
+
+
+SEE ALSO
+--------
+linkmb:modbus_rtu_get_rts_delay[3]
+
+
+AUTHORS
+-------
+Jimmy Bergström <jimmy@ekontroll.com>
+
+The libmodbus documentation was written by Stéphane Raimbault
+<stephane.raimbault@gmail.com>

+ 1 - 4
src/modbus-rtu-private.h

@@ -25,10 +25,6 @@
 
 #define _MODBUS_RTU_CHECKSUM_LENGTH    2
 
-/* Time waited beetween the RTS switch before transmit data or after transmit
-   data before to read (1 ms) */
-#define _MODBUS_RTU_TIME_BETWEEN_RTS_SWITCH 1000
-
 #if defined(_WIN32)
 #if !defined(ENOTSUP)
 #define ENOTSUP WSAEOPNOTSUPP
@@ -69,6 +65,7 @@ typedef struct _modbus_rtu {
 #endif
 #if HAVE_DECL_TIOCM_RTS
     int rts;
+    int rts_delay;
     int onebyte_time;
     void (*set_rts) (modbus_t *ctx, int on);
 #endif

+ 57 - 3
src/modbus-rtu.c

@@ -284,11 +284,11 @@ static ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_lengt
         }
 
         ctx_rtu->set_rts(ctx, ctx_rtu->rts == MODBUS_RTU_RTS_UP);
-        usleep(_MODBUS_RTU_TIME_BETWEEN_RTS_SWITCH);
+        usleep(ctx_rtu->rts_delay);
 
         size = write(ctx->s, req, req_length);
 
-        usleep(ctx_rtu->onebyte_time * req_length + _MODBUS_RTU_TIME_BETWEEN_RTS_SWITCH);
+        usleep(ctx_rtu->onebyte_time * req_length + ctx_rtu->rts_delay);
         ctx_rtu->set_rts(ctx, ctx_rtu->rts != MODBUS_RTU_RTS_UP);
 
         return size;
@@ -1028,6 +1028,57 @@ int modbus_rtu_get_rts(modbus_t *ctx)
     }
 }
 
+int modbus_rtu_set_rts_delay(modbus_t *ctx, int us)
+{
+    if (ctx == NULL || us < 0) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) {
+#if HAVE_DECL_TIOCM_RTS
+        modbus_rtu_t *ctx_rtu;
+        ctx_rtu = (modbus_rtu_t *)ctx->backend_data;
+        ctx_rtu->rts_delay = us;
+        return 0;
+#else
+        if (ctx->debug) {
+            fprintf(stderr, "This function isn't supported on your platform\n");
+        }
+        errno = ENOTSUP;
+        return -1;
+#endif
+    } else {
+        errno = EINVAL;
+        return -1;
+    }
+}
+
+int modbus_rtu_get_rts_delay(modbus_t *ctx)
+{
+    if (ctx == NULL) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) {
+#if HAVE_DECL_TIOCM_RTS
+        modbus_rtu_t *ctx_rtu;
+        ctx_rtu = (modbus_rtu_t *)ctx->backend_data;
+        return ctx_rtu->rts_delay;
+#else
+        if (ctx->debug) {
+            fprintf(stderr, "This function isn't supported on your platform\n");
+        }
+        errno = ENOTSUP;
+        return -1;
+#endif
+    } else {
+        errno = EINVAL;
+        return -1;
+    }
+}
+
 int modbus_rtu_set_custom_rts(modbus_t *ctx, void (*set_rts) (modbus_t *ctx, int on))
 {
     if (ctx == NULL) {
@@ -1209,9 +1260,12 @@ modbus_t* modbus_new_rtu(const char *device,
     ctx_rtu->rts = MODBUS_RTU_RTS_NONE;
 
     /* Calculate estimated time in micro second to send one byte */
-    ctx_rtu->onebyte_time = (1000 * 1000) * (1 + data_bit + (parity == 'N' ? 0 : 1) + stop_bit) / baud;
+    ctx_rtu->onebyte_time = 1000000 * (1 + data_bit + (parity == 'N' ? 0 : 1) + stop_bit) / baud;
 
     ctx_rtu->set_rts = _modbus_rtu_ioctl_rts;
+
+    /* The delay before and after transmission when toggling the RTS pin */
+    ctx_rtu->rts_delay = ctx_rtu->onebyte_time;
 #endif
 
     ctx_rtu->confirmation_to_ignore = FALSE;

+ 3 - 0
src/modbus-rtu.h

@@ -33,6 +33,9 @@ MODBUS_API int modbus_rtu_set_rts(modbus_t *ctx, int mode);
 MODBUS_API int modbus_rtu_get_rts(modbus_t *ctx);
 MODBUS_API int modbus_rtu_set_custom_rts(modbus_t *ctx, void (*set_rts) (modbus_t *ctx, int on));
 
+MODBUS_API int modbus_rtu_set_rts_delay(modbus_t *ctx, int us);
+MODBUS_API int modbus_rtu_get_rts_delay(modbus_t *ctx);
+
 MODBUS_END_DECLS
 
 #endif /* MODBUS_RTU_H */