RS-485 ist ein einfacher Standard auf der physikalischen Schicht für ein Netzwerk zur seriellen Datenübertragung über differentielle Leitungen. Es gibt Leitungstreiber für Full-Duplex (2 differentielle Leitungen, also 4 Drähte) und für Halb-Duplex Anwendungen (1 differentielle Leitung, also 2 Drähte).
Know How
The Art and Science of RS-485 (Elektronische Sicht)
Bauteile
Pegelwandelnde Transceiver
Überblick bei mikrocontroller.net
Converter
RS-232 to RS-485 (full/half duplex) mit automatischem Richtungswechsel, was das Problem am Linux PC löst.
Problem: RS-485 am Linux PC
Als nicht ganz so einfach stellt sich das Anschließen eines Halb-Duplex RS-485 Busses an einen Linux PC heraus.
Naheliegend ist das Anschließen eines RS-485 Leitungstreibers (und Pegelwandlers) über einen RS-232 Pegelwandler (z.B. MAX232) an den Seriellen Port des PCs.
Der Receiverausgang zum PC muss ausgeschaltet werden, während Daten gesendet werden, wenn da der PC nicht gleichzeitig sein gesendetes wieder empfangen soll. Es liegt die verwendung der RTS Leitung des Seriellen Ports nahe, um über den RE eingang des RS-485 Transceivers seinen Receiverausgang zu deaktivieren. Unter Windows gibt es eine API configuration RTS_CONTROL_TOGGLE, mit der das genau so funktioniert. Unter Linux geht das nicht automatisch, das CRTSCTS flag in der termios c_cflag Struktur macht etwas anderes. Die RTS Leitung kann unter Linux mit einem ioctl() Aufruf unter Verwendung des TIOCMSET Kommandos geschaltet werden (siehe auch: Serial Programming Guide for POSIX Operating Systems):
/* POSIX: */
int controlbits;
ioctl(fd, TIOCMGET, &controlbits);
/* RTS setzten: */
controlbits |= TIOCM_RTS;
/* RTS löschen: */
//controlbits &= ~TIOCM_RTS;
ioctl(fd, TIOCMSET, &controlbits);
oder
/* LINUX(?): */
int controlbits = TIOCM_RTS;
ioctl(tty_fd, (on ? TIOCMBIS : TIOCMBIC), &controlbits);
Dieser Systemaufruf geschieht allerdings nicht in Echtzeit und so entsteht ein nicht kontrollierbares Delay zwischen ioctl() Aufruf und Änderung an der RTS Leitung. Das Schalten der RTS Leitung ist so nicht mit dem Senden von Daten zu synchronisieren.
Lösungsansätze:
> I think there's a way you can get notification when the > transmit buffer is empty and then switch rts off. He can call tcdrain() and then use TCIOMCLR to turn off RTS, but I've never had much luck with that. tcdrain() often returns before all data has actually been sent. Calling tcdrain() and then delaying for a byte time or two might work if the turn-around time for the interface is several byte times long.
> Perhaps you can use setitimer() to alert you when all your bytes > have been sent so you can clear the RTS bit, That might work if there is no flow control _and_ you can somehow sync up the setitimer() call to the point in time when the transmission started, _and_ you can guarantee there are no other running processes (or you use Posix real-time threads). In any case, the timing of software stuff generally has the same granularity as the system tick (4ms or 10ms typically), which is just way too long for anything faster than 300 baud). The right way to do RTS toggle is in hardware. Doing it in the driver using interrupts is sometimes a workable hack. Doing it in user space rarely works.
Pin verändern mit outb()?
In den RS-232 <=> RS-485 Adapter einbauen. Evtl mit einem Microcontroller, der als Gateway zwischen RS-485 Treiber und RS-232 Treiber sitzt.
Oder einfach als readback Feature benutzen, um zu checken, ob die Daten richtig auf dem Bus gelandet sind. Wird bei CAN auch so gemacht(?) Das muss dann natürlich in Software realisiert werden und der Bus funktioniert dann nicht mehr wie eine verlängerte RS-232 Leitung. Es sei denn, es wird als Treiber realisiert. Oder in Hardware, siehe oben.