Die serielle Schnittstelle wurde im PC ursprünglich durch den Baustein 8250 realisiert. Die Funktionen dieses UART (Universal Asynchronous Receiver/Transmitter) sind inzwischen auf einem der VLSI-Chips (Very Large Scale Integration) des PC-Chipsatzes integriert, dadurch auch etwas erweitert worden (u. a. bessere Datenpufferung). Die direkte Programmierung ist aus Kompatibilitätsgründen nach wie vor über die 'klassischen' Register des 8250 möglich. Eine ausführliche Übersicht über diese Register gibt ein Vorlesungsskript aus der DOS-Epoche (PDF-Format oder PS-Format).
Unter Linux sind Konstanten für die Register-Offsets und die Register-Inhalte in der Header-Datei <linux/serial_reg.h> definiert, diese sollten verwendet werden, um die Programme verständlich und selbstdokumentierend zu machen. Der folgende Auszug daraus betrifft das MODEM-Kontroll-Register, über das die Handshake-Ausgänge RTS und DTR der seriellen Schnittstelle gesetzt werden können:
... #define UART_MCR 4 /* Out: Modem Control Register */ ... #define UART_MCR_RTS 0x02 /* RTS complement */ #define UART_MCR_DTR 0x01 /* DTR complement */ ... |
Die Basisadressen der seriellen Schnittstellen können bei moderneren Rechnern aus dem ROM-Bios abgelesen werden, meist werden die Adressen auch beim Hochfahren des Rechners gemeldet. Unter Linux sind die Adressen außerdem in <asm/serial.h> definiert.
Als Anwendungsbeispiel ein Programmfragment, das bei jedem Aufruf den Status der RTS-Leitung der Schnittstelle COM1 invertiert (über die Leitung könnte beispielsweise ein Halbleiterrelais betrieben werden, mit dem ein elektrisches Gerät geschaltet wird):
const unsigned short SERIALBASE = 0x3F8; /* COM1 */ int main(void) { int data; check(ioperm(SERIALBASE, 7, 1), "ioperm"); data = inb(SERIALBASE+UART_MCR); data ^= UART_MCR_RTS; outb(data, SERIALBASE+UART_MCR); check(ioperm(SERIALBASE, 7, 0), "ioperm"); return 0; } |