Commit 9bf830959754a8909a8477fdd238dfb31e3216ce
1 parent
bb23b4ab
Add functions to set/get RS485 communications on Linux
Showing
5 changed files
with
63 additions
and
2 deletions
NEWS
| @@ -18,7 +18,8 @@ libmodbus 2.9.4 (2011-05-XX) | @@ -18,7 +18,8 @@ libmodbus 2.9.4 (2011-05-XX) | ||
| 18 | * modbus_set_timeout_begin -> modbus_set_response_timeout | 18 | * modbus_set_timeout_begin -> modbus_set_response_timeout |
| 19 | * modbus_get_timeout_end -> modbus_get_byte_timeout | 19 | * modbus_get_timeout_end -> modbus_get_byte_timeout |
| 20 | * modbus_set_timeout_end -> modbus_set_byte_timeout | 20 | * modbus_set_timeout_end -> modbus_set_byte_timeout |
| 21 | - | 21 | +- New functions modbus_set/get_serial_mode by Manfred Gruber and Stéphane |
| 22 | + Raimbault for RS485 communications | ||
| 22 | 23 | ||
| 23 | libmodbus 2.9.3 (2011-01-14) | 24 | libmodbus 2.9.3 (2011-01-14) |
| 24 | ============================ | 25 | ============================ |
configure.ac
| @@ -77,6 +77,7 @@ AC_CHECK_HEADERS([ \ | @@ -77,6 +77,7 @@ AC_CHECK_HEADERS([ \ | ||
| 77 | netinet/tcp.h \ | 77 | netinet/tcp.h \ |
| 78 | arpa/inet.h \ | 78 | arpa/inet.h \ |
| 79 | netdb.h \ | 79 | netdb.h \ |
| 80 | + linux/serial.h \ | ||
| 80 | ]) | 81 | ]) |
| 81 | 82 | ||
| 82 | # Check whether to build docs / install man pages | 83 | # Check whether to build docs / install man pages |
src/modbus-rtu-private.h
| @@ -74,6 +74,7 @@ typedef struct _modbus_rtu { | @@ -74,6 +74,7 @@ typedef struct _modbus_rtu { | ||
| 74 | #else | 74 | #else |
| 75 | /* Save old termios settings */ | 75 | /* Save old termios settings */ |
| 76 | struct termios old_tios; | 76 | struct termios old_tios; |
| 77 | + int serial_mode; | ||
| 77 | #endif | 78 | #endif |
| 78 | } modbus_rtu_t; | 79 | } modbus_rtu_t; |
| 79 | 80 |
src/modbus-rtu.c
| @@ -30,6 +30,11 @@ | @@ -30,6 +30,11 @@ | ||
| 30 | #include "modbus-rtu.h" | 30 | #include "modbus-rtu.h" |
| 31 | #include "modbus-rtu-private.h" | 31 | #include "modbus-rtu-private.h" |
| 32 | 32 | ||
| 33 | +#if defined(linux) | ||
| 34 | +#include <sys/ioctl.h> | ||
| 35 | +#include <linux/serial.h> | ||
| 36 | +#endif | ||
| 37 | + | ||
| 33 | /* Table of CRC values for high-order byte */ | 38 | /* Table of CRC values for high-order byte */ |
| 34 | static const uint8_t table_crc_hi[] = { | 39 | static const uint8_t table_crc_hi[] = { |
| 35 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, | 40 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, |
| @@ -692,11 +697,55 @@ static int _modbus_rtu_connect(modbus_t *ctx) | @@ -692,11 +697,55 @@ static int _modbus_rtu_connect(modbus_t *ctx) | ||
| 692 | if (tcsetattr(ctx->s, TCSANOW, &tios) < 0) { | 697 | if (tcsetattr(ctx->s, TCSANOW, &tios) < 0) { |
| 693 | return -1; | 698 | return -1; |
| 694 | } | 699 | } |
| 695 | -#endif | ||
| 696 | 700 | ||
| 701 | + /* The RS232 mode has been set by default */ | ||
| 702 | + ctx_rtu->serial_mode = MODBUS_RTU_RS232; | ||
| 703 | +#endif | ||
| 697 | return 0; | 704 | return 0; |
| 698 | } | 705 | } |
| 699 | 706 | ||
| 707 | +#if defined(linux) | ||
| 708 | +int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode) | ||
| 709 | +{ | ||
| 710 | + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { | ||
| 711 | + modbus_rtu_t *ctx_rtu = ctx->backend_data; | ||
| 712 | + struct serial_rs485 rs485conf; | ||
| 713 | + memset(&rs485conf, 0x0, sizeof(struct serial_rs485)); | ||
| 714 | + | ||
| 715 | + if (mode == MODBUS_RTU_RS485) { | ||
| 716 | + rs485conf.flags = SER_RS485_ENABLED; | ||
| 717 | + if (ioctl(ctx->s, TIOCSRS485, &rs485conf) < 0) { | ||
| 718 | + return -1; | ||
| 719 | + } | ||
| 720 | + | ||
| 721 | + ctx_rtu->serial_mode |= MODBUS_RTU_RS485; | ||
| 722 | + return 0; | ||
| 723 | + } else if (mode == MODBUS_RTU_RS232) { | ||
| 724 | + if (ioctl(ctx->s, TIOCSRS485, &rs485conf) < 0) { | ||
| 725 | + return -1; | ||
| 726 | + } | ||
| 727 | + | ||
| 728 | + ctx_rtu->serial_mode = MODBUS_RTU_RS232; | ||
| 729 | + return 0; | ||
| 730 | + } | ||
| 731 | + } | ||
| 732 | + | ||
| 733 | + /* Wrong backend and invalid mode specified */ | ||
| 734 | + errno = EINVAL; | ||
| 735 | + return -1; | ||
| 736 | +} | ||
| 737 | + | ||
| 738 | +int modbus_rtu_get_serial_mode(modbus_t *ctx) { | ||
| 739 | + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { | ||
| 740 | + modbus_rtu_t *ctx_rtu = ctx->backend_data; | ||
| 741 | + return ctx_rtu->serial_mode; | ||
| 742 | + } else { | ||
| 743 | + errno = EINVAL; | ||
| 744 | + return -1; | ||
| 745 | + } | ||
| 746 | +} | ||
| 747 | +#endif | ||
| 748 | + | ||
| 700 | void _modbus_rtu_close(modbus_t *ctx) | 749 | void _modbus_rtu_close(modbus_t *ctx) |
| 701 | { | 750 | { |
| 702 | /* Closes the file descriptor in RTU mode */ | 751 | /* Closes the file descriptor in RTU mode */ |
src/modbus-rtu.h
| @@ -28,4 +28,13 @@ | @@ -28,4 +28,13 @@ | ||
| 28 | modbus_t* modbus_new_rtu(const char *device, int baud, char parity, | 28 | modbus_t* modbus_new_rtu(const char *device, int baud, char parity, |
| 29 | int data_bit, int stop_bit); | 29 | int data_bit, int stop_bit); |
| 30 | 30 | ||
| 31 | +#if defined(linux) | ||
| 32 | +/* On Linux, we can tell the kernel for RS485 communication */ | ||
| 33 | +#define MODBUS_RTU_RS232 0 | ||
| 34 | +#define MODBUS_RTU_RS485 1 | ||
| 35 | + | ||
| 36 | +int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode); | ||
| 37 | +int modbus_rtu_get_serial_mode(modbus_t *ctx); | ||
| 38 | +#endif | ||
| 39 | + | ||
| 31 | #endif /* _MODBUS_RTU_H_ */ | 40 | #endif /* _MODBUS_RTU_H_ */ |