Difference between revisions of "RS-485"
From ArmadeusWiki
(New page: = RS485 = Informations and mini HOWTOs for the APF28/iMX28 mxs-auart and busybox stty patches. Author: JanosA == Linux stty == * Setup APF28 serial port for RS485 communication: <pre cl...) |
(→Links) |
||
(13 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
− | + | Informations and HOWTOs for ArmadeuS RS-485 support. | |
− | Informations and | + | |
− | + | RS-485 mostly used in half duplex operation mode, and uses a differential balanced line over twisted pair. RS-485 drivers need to be put in transmit mode explicitly by asserting a signal to the driver. This allows RS-485 to implement linear topologies using only two wires, and it can span relatively large distances (up to 1,200m @ 100kbit/s). | |
− | == Linux stty == | + | Before the RS-485 related parts, please have a look on: [[Serial ports usage on Linux]] |
− | * Setup APF28 serial port for | + | |
+ | Author: [[Users:JanosA]] | ||
+ | |||
+ | == Supported Board and Software versions == | ||
+ | * Use the latest Armadeus GIT/SF repository or the latest stable release. | ||
+ | * Currently tested only on the [[APF28]] (i.MX28) board with Linux kernel 2.6.35 (patch 462) and 4.9 (patch 703). If device tree is used, you need to activate rts/cts on UART used for RS-485. | ||
+ | * Busybox ''stty'' command requires a patch included in Armadeus BSP, to handle specifics RS-485 parameters handling. | ||
+ | |||
+ | == Changing port parameters == | ||
+ | * Setup APF28 serial port for RS-485 communication: | ||
<pre class=apf> | <pre class=apf> | ||
− | # | + | # export SERIAL_DEV=/dev/ttySP0 |
− | # stty -F | + | # stty -F $SERIAL_DEV 9600 |
− | # stty -F | + | # stty -F $SERIAL_DEV raw |
+ | # stty -F $SERIAL_DEV -echo -echoe -echok | ||
+ | # stty -F $SERIAL_DEV rs485 | ||
</pre> | </pre> | ||
− | * Set extra delays for TXEN/RTS signaling before and after the transmitted packet (in microseconds): | + | * Set extra delays (if needed) for TXEN/RTS signaling before and after the transmitted packet (in microseconds): |
<pre class=apf> | <pre class=apf> | ||
− | # stty -F | + | # stty -F $SERIAL_DEV rs485delaybefore 100 |
− | # stty -F | + | # stty -F $SERIAL_DEV rs485delayafter 100 |
</pre> | </pre> | ||
− | * To get current | + | * To get current RS-485 parameters: (if the serial port supports the RS-485 options, you will see previous rs485 parameters values) |
<pre class=apf> | <pre class=apf> | ||
# stty -F /dev/ttySP0 | # stty -F /dev/ttySP0 | ||
Line 31: | Line 41: | ||
Please note: | Please note: | ||
* You can't set the "rs485delaylastchartx" parameter, it's calculated automatically from the baudrate. | * You can't set the "rs485delaylastchartx" parameter, it's calculated automatically from the baudrate. | ||
− | Special notes for the APF28/ | + | Special notes for the APF28/i.MX28 ''mxs-auart'' driver: |
* All delays are in microseconds. | * All delays are in microseconds. | ||
* The "rs485delaylastchartx" parameter is not used in DMA mode. | * The "rs485delaylastchartx" parameter is not used in DMA mode. | ||
* The parameters: "rs485rtsonsend" "rs485rtsaftersend" "rs485rxduringtx" are not used. (Only used by atmel_serial.c and crisv10.c drivers) | * The parameters: "rs485rtsonsend" "rs485rtsaftersend" "rs485rxduringtx" are not used. (Only used by atmel_serial.c and crisv10.c drivers) | ||
− | * If the | + | * If the RS-485 mode is turned on, it will override (turn off) the RTS/CTS hardware flow settings of the UART, whatever is configured. |
− | + | == How to use it from C code == | |
− | == C code == | + | * The RS-485 mode can also be turned on with ioctl calls from C code, here is the example: |
− | * The | + | |
<source lang="C"> | <source lang="C"> | ||
#include <stdio.h> | #include <stdio.h> | ||
Line 56: | Line 65: | ||
− | /* Don't forget to read first the current state of the | + | /* Don't forget to read first the current state of the RS-485 options with ioctl. |
If You don't do this, You will destroy the rs485conf.delay_rts_last_char_tx | If You don't do this, You will destroy the rs485conf.delay_rts_last_char_tx | ||
parameter which is automatically calculated by the driver when You opens the | parameter which is automatically calculated by the driver when You opens the | ||
Line 64: | Line 73: | ||
} | } | ||
− | /* Enable | + | /* Enable RS-485 mode: */ |
rs485conf.flags |= SER_RS485_ENABLED; | rs485conf.flags |= SER_RS485_ENABLED; | ||
Line 88: | Line 97: | ||
} | } | ||
</source> | </source> | ||
− | |||
== Hardware Notes == | == Hardware Notes == | ||
− | * The | + | * The RS-485 Transmit Enable (TXEN) output will be the RTS pin of the UART. |
− | * The TXEN/RTS output is _active low_, it must be inverted to use it with the popular | + | * The TXEN/RTS output is _active low_, it must be inverted to use it with the popular RS-485 transceiver ICs. On kernel with device tree, this can be done with ''rs485-rts-active-high'' option when declaring UART config. |
− | * When | + | * When U-Boot runs and the board start to boot, the RTS pin works as an input, so please add a pull-up resistor to this pin, before the inverter, to prevent RS-485 bus lockups. |
+ | |||
+ | ==Links== | ||
+ | * Some C example code to use Modbus RTU through RS485: https://github.com/artemysfr/embedded-tools | ||
+ | * De-asserting RTS fastest as possible is a well known problem on every platforms: | ||
+ | ** https://blog.savoirfairelinux.com/en-ca/2013/adding-rs-485-support-to-the-beaglebone-with-short-turnaround-delay/ | ||
+ | |||
+ | [[Category:Serial ports]] | ||
+ | [[Category:RS485]] | ||
+ | [[Category:Modbus]] |
Latest revision as of 17:41, 1 April 2022
Informations and HOWTOs for ArmadeuS RS-485 support.
RS-485 mostly used in half duplex operation mode, and uses a differential balanced line over twisted pair. RS-485 drivers need to be put in transmit mode explicitly by asserting a signal to the driver. This allows RS-485 to implement linear topologies using only two wires, and it can span relatively large distances (up to 1,200m @ 100kbit/s).
Before the RS-485 related parts, please have a look on: Serial ports usage on Linux
Author: Users:JanosA
Contents
Supported Board and Software versions
- Use the latest Armadeus GIT/SF repository or the latest stable release.
- Currently tested only on the APF28 (i.MX28) board with Linux kernel 2.6.35 (patch 462) and 4.9 (patch 703). If device tree is used, you need to activate rts/cts on UART used for RS-485.
- Busybox stty command requires a patch included in Armadeus BSP, to handle specifics RS-485 parameters handling.
Changing port parameters
- Setup APF28 serial port for RS-485 communication:
# export SERIAL_DEV=/dev/ttySP0 # stty -F $SERIAL_DEV 9600 # stty -F $SERIAL_DEV raw # stty -F $SERIAL_DEV -echo -echoe -echok # stty -F $SERIAL_DEV rs485
- Set extra delays (if needed) for TXEN/RTS signaling before and after the transmitted packet (in microseconds):
# stty -F $SERIAL_DEV rs485delaybefore 100 # stty -F $SERIAL_DEV rs485delayafter 100
- To get current RS-485 parameters: (if the serial port supports the RS-485 options, you will see previous rs485 parameters values)
# stty -F /dev/ttySP0 speed 9600 baud; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0; -brkint -imaxbel rs485 -rs485rtsonsend -rs485rtsaftersend -rs485rxduringtx rs485delaybefore = 100; rs485delayafter = 100; rs485delaylastchartx = 1250;
Please note:
- You can't set the "rs485delaylastchartx" parameter, it's calculated automatically from the baudrate.
Special notes for the APF28/i.MX28 mxs-auart driver:
- All delays are in microseconds.
- The "rs485delaylastchartx" parameter is not used in DMA mode.
- The parameters: "rs485rtsonsend" "rs485rtsaftersend" "rs485rxduringtx" are not used. (Only used by atmel_serial.c and crisv10.c drivers)
- If the RS-485 mode is turned on, it will override (turn off) the RTS/CTS hardware flow settings of the UART, whatever is configured.
How to use it from C code
- The RS-485 mode can also be turned on with ioctl calls from C code, here is the example:
#include <stdio.h>
#include <fcntl.h>
#include <linux/ioctl.h>
#include <linux/serial.h>
#include <asm-generic/ioctls.h> /* TIOCGRS485 + TIOCSRS485 ioctl definitions */
int main(void) {
struct serial_rs485 rs485conf;
int fd = open ("/dev/ttySP0", O_RDWR);
if (fd < 0) {
printf("Error: Can't open: /dev/ttySP0\n");
}
/* Don't forget to read first the current state of the RS-485 options with ioctl.
If You don't do this, You will destroy the rs485conf.delay_rts_last_char_tx
parameter which is automatically calculated by the driver when You opens the
port device. */
if (ioctl (fd, TIOCGRS485, &rs485conf) < 0) {
printf("Error: TIOCGRS485 ioctl not supported.\n");
}
/* Enable RS-485 mode: */
rs485conf.flags |= SER_RS485_ENABLED;
/* Set rts/txen delay before send, if needed: (in microseconds) */
rs485conf.delay_rts_before_send = 0;
/* Set rts/txen delay after send, if needed: (in microseconds) */
rs485conf.delay_rts_after_send = 0;
if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) {
printf("Error: TIOCSRS485 ioctl not supported.\n");
}
fcntl(fd, F_SETFL, 0);
int n = write(fd, "ABC\r\n", 5);
if (n < 0) {
/* Error handling */
}
if (close (fd) < 0) {
printf("Error: Can't close: /dev/ttySP0\n");
}
}
Hardware Notes
- The RS-485 Transmit Enable (TXEN) output will be the RTS pin of the UART.
- The TXEN/RTS output is _active low_, it must be inverted to use it with the popular RS-485 transceiver ICs. On kernel with device tree, this can be done with rs485-rts-active-high option when declaring UART config.
- When U-Boot runs and the board start to boot, the RTS pin works as an input, so please add a pull-up resistor to this pin, before the inverter, to prevent RS-485 bus lockups.
Links
- Some C example code to use Modbus RTU through RS485: https://github.com/artemysfr/embedded-tools
- De-asserting RTS fastest as possible is a well known problem on every platforms: