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 | 18 | * modbus_set_timeout_begin -> modbus_set_response_timeout |
| 19 | 19 | * modbus_get_timeout_end -> modbus_get_byte_timeout |
| 20 | 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 | 24 | libmodbus 2.9.3 (2011-01-14) |
| 24 | 25 | ============================ | ... | ... |
configure.ac
src/modbus-rtu-private.h
src/modbus-rtu.c
| ... | ... | @@ -30,6 +30,11 @@ |
| 30 | 30 | #include "modbus-rtu.h" |
| 31 | 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 | 38 | /* Table of CRC values for high-order byte */ |
| 34 | 39 | static const uint8_t table_crc_hi[] = { |
| 35 | 40 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, |
| ... | ... | @@ -692,11 +697,55 @@ static int _modbus_rtu_connect(modbus_t *ctx) |
| 692 | 697 | if (tcsetattr(ctx->s, TCSANOW, &tios) < 0) { |
| 693 | 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 | 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 | 749 | void _modbus_rtu_close(modbus_t *ctx) |
| 701 | 750 | { |
| 702 | 751 | /* Closes the file descriptor in RTU mode */ | ... | ... |
src/modbus-rtu.h
| ... | ... | @@ -28,4 +28,13 @@ |
| 28 | 28 | modbus_t* modbus_new_rtu(const char *device, int baud, char parity, |
| 29 | 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 | 40 | #endif /* _MODBUS_RTU_H_ */ | ... | ... |