Reihe: Embedded World – Die unsichtbaren Gehirne verstehen (Teil 7)

Der Wald der Schnittstellen – Kommunikation im Kleinen (UART, I2C, SPI)

Von DerSchneider


Einleitung: Die Sprache der Geräte

Bisher haben wir uns mit dem Inneren eines Embedded Systems beschäftigt – mit seiner Architektur, seinem Takt, seiner direkten Kommunikation über Register und Interrupts. Doch ein System allein ist selten. In der realen Welt müssen Mikrocontroller mit anderen Komponenten sprechen: mit Sensoren, die Daten liefern, mit Aktoren, die Befehle ausführen, mit Speicherchips, die mehr Platz bieten, mit anderen Controllern, die zusammenarbeiten.

Für diese Gespräche braucht es gemeinsame Sprachen – standardisierte Protokolle, die festlegen, wie Bits übertragen werden, wer wann sprechen darf und wie Fehler vermieden werden. In der Embedded World haben sich drei Protokolle als die unangefochtenen Standards etabliert: UART, I2C und SPI. Jedes hat seine Stärken, seine Schwächen und seinen typischen Einsatzzweck.

Dieser Artikel führt durch diesen Wald der Schnittstellen. Wir lernen die drei großen „Sprachen“ der Embedded-Kommunikation kennen, verstehen ihre Unterschiede und wissen, wann man welche einsetzt.


Hauptteil

1. Die Grundbegriffe: Was alle Protokolle gemeinsam haben

Bevor wir in die Details der einzelnen Protokolle einsteigen, klären wir einige Begriffe, die für alle gelten:

Synchron vs. Asynchron: Bei synchroner Kommunikation gibt es ein separates Taktsignal, das den Rhythmus vorgibt. Sender und Empfänger sind durch diesen gemeinsamen Takt verbunden. Bei asynchroner Kommunikation gibt es keinen gemeinsamen Takt – beide Seiten müssen sich vorher auf eine Geschwindigkeit (Baudrate) einigen und den Takt selbst erzeugen.

Seriell vs. Parallel: Serielle Kommunikation überträgt Bits nacheinander über eine Leitung. Parallele Kommunikation überträgt mehrere Bits gleichzeitig über mehrere Leitungen. Seriell ist langsamer, braucht aber weniger Leitungen – in der Embedded World fast immer die bessere Wahl.

Halbduplex vs. Vollduplex: Halbduplex bedeutet, dass in beide Richtungen gesendet werden kann, aber nicht gleichzeitig. Vollduplex erlaubt gleichzeitiges Senden und Empfangen.

Master vs. Slave: In vielen Protokollen gibt es einen Master, der den Takt vorgibt und die Kommunikation steuert, und einen oder mehrere Slaves, die antworten. (Die Begriffe sind historisch gewachsen und werden zunehmend durch alternative Bezeichnungen wie „Controller“ und „Peripheral“ ersetzt.)

2. Der Urvater: UART (Universal Asynchronous Receiver Transmitter)

Beginnen wir mit dem ältesten und einfachsten Protokoll: UART. Es ist die Grundlage der klassischen seriellen Schnittstelle, wie sie früher an Computern für Maus und Modem verwendet wurde.

Prinzip: UART ist asynchron und arbeitet mit nur zwei Leitungen: TX (Senden) und RX (Empfangen). Beide Seiten müssen sich vorher auf eine gemeinsame Geschwindigkeit einigen – die Baudrate, typisch 9600, 115200 oder 1.000.000 Bit pro Sekunde.

Wenn keine Daten gesendet werden, liegt die Leitung auf HIGH (logisch 1). Der Beginn einer Übertragung wird durch ein Startbit markiert (Leitung auf LOW). Dann folgen die Datenbits (meist 8), oft ein Parity-Bit zur Fehlererkennung, und mindestens ein Stopbit (wieder HIGH), das das Ende markiert.

Stärken:

  • Einfach und seit Jahrzehnten etabliert
  • Kommt mit nur zwei Leitungen aus (bei bidirektionaler Kommunikation)
  • Weit verbreitet, jeder Mikrocontroller hat mindestens eine UART-Hardware
  • Einfach zu debuggen – man kann alles mit einem USB-Seriell-Wandler am PC mitlesen

Schwächen:

  • Punkt-zu-Punkt-Verbindung – nur zwei Teilnehmer möglich
  • Asynchron – beide Seiten müssen genau die gleiche Taktfrequenz haben, sonst gibt es Bitfehler
  • Relativ langsam (typisch bis 1 Mbit/s, manchmal mehr)

Typische Anwendungen:

  • Debug-Ausgabe vom Mikrocontroller zum PC
  • Kommunikation mit GPS-Modulen, Bluetooth-HCs, manchen Sensoren
  • Verbindung zwischen zwei Mikrocontrollern

In der Arduino-Welt ist UART allgegenwärtig. Der serielle Monitor, über den wir Daten anzeigen, nutzt genau dieses Protokoll.

3. Der Alleskönner: I2C (Inter-Integrated Circuit)

I2C, entwickelt von Philips in den 1980er Jahren, ist der Star unter den Embedded-Protokollen. Es erlaubt, viele Geräte mit nur zwei Leitungen zu verbinden.

Prinzip: I2C braucht zwei Leitungen: SCL (Clock) für den Takt und SDA (Data) für die Daten. Beide Leitungen sind „Open-Drain“ – sie werden über Pull-up-Widerstände auf HIGH gezogen, und jedes Gerät kann sie auf LOW ziehen.

Es gibt immer einen Master (meist der Mikrocontroller), der den Takt vorgibt. Jedes Gerät hat eine eindeutige Adresse (7 oder 10 Bit). Wenn der Master mit einem bestimmten Gerät sprechen will, sendet er dessen Adresse auf den Bus. Das adressierte Gerät antwortet, und dann können Daten ausgetauscht werden.

Stärken:

  • Viele Geräte (theoretisch bis zu 127) an nur zwei Leitungen
  • Einfach zu erweitern – einfach neue Geräte dazu stecken
  • Geräte können Master und Slave sein (Multi-Master-Fähigkeit)
  • Weit verbreitet – unzählige Sensoren, Speicher, Displays nutzen I2C

Schwächen:

  • Relativ langsam (typisch 100 kHz oder 400 kHz, manchmal bis 3,4 MHz)
  • Adresskonflikte möglich, wenn zwei gleiche Geräte die gleiche Adresse haben
  • Die Pull-up-Widerstände müssen richtig dimensioniert sein
  • Bei langen Leitungen anfällig für Störungen

Typische Anwendungen:

  • Sensoren (Temperatur, Luftfeuchtigkeit, Druck, Helligkeit)
  • Kleine EEPROM-Speicher
  • Displays (OLED, LCD mit I2C-Adapter)
  • Echtzeituhren (RTC)

I2C ist der ideale Bus für die Innenwelt eines Geräts – viele Komponenten, wenige Leitungen, gemächliches Tempo.

4. Der Sprinter: SPI (Serial Peripheral Interface)

Wenn es schnell gehen muss, kommt SPI zum Einsatz. Es ist das Rennpferd unter den Embedded-Protokollen.

Prinzip: SPI braucht vier Leitungen:

  • SCLK (Serial Clock): Der Takt vom Master
  • MOSI (Master Out Slave In): Daten vom Master zum Slave
  • MISO (Master In Slave Out): Daten vom Slave zum Master
  • SS (Slave Select): Eine Leitung pro Slave, mit der der Master den gewünschten Teilnehmer aktiviert

SPI ist vollduplex – es können gleichzeitig Daten in beide Richtungen fließen. Der Master gibt den Takt vor und wählt durch das SS-Signal aus, mit welchem Slave er spricht. Alle anderen Slaves ignorieren den Bus.

Stärken:

  • Sehr schnell (typisch 10-50 MHz, manchmal mehr)
  • Vollduplex – gleichzeitiges Senden und Empfangen
  • Einfache Hardware, keine aufwendige Protokoll-Logik
  • Beliebig erweiterbar (durch zusätzliche SS-Leitungen)

Schwächen:

  • Viele Leitungen (mindestens 3 + eine pro Slave)
  • Kein standardisiertes Protokoll auf höherer Ebene – jeder Hersteller macht, was er will
  • Keine Adressierung – der Master muss jeden Slave einzeln ansteuern
  • Begrenzte Entfernungen (eher für Board-intern)

Typische Anwendungen:

  • SD-Karten
  • Display mit hoher Bildwiederholrate
  • Schnelle AD-Wandler
  • Flash-Speicherchips
  • Kommunikation zwischen FPGAs und Mikrocontrollern

SPI ist die Wahl, wenn es auf Geschwindigkeit ankommt – aber der Preis ist mehr Leitungen und komplexere Verkabelung bei vielen Geräten.

5. Vergleich: Wann nehme ich was?

Die folgende Übersicht hilft bei der Wahl:

KriteriumUARTI2CSPI
Leitungen2 (TX/RX)2 (SDA/SCL)3 + n (SCLK, MOSI, MISO + SS pro Slave)
Teilnehmer2Viele (Adressen)Viele (über SS)
GeschwindigkeitMittel (bis ~1 Mbit/s)Langsam (100 kHz – 3,4 MHz)Hoch (10-50 MHz)
SynchronitätAsynchronSynchronSynchron
DuplexHalbduplex (meist)HalbduplexVollduplex
KomplexitätSehr einfachMittel (Protokoll)Einfach (Hardware)
EntfernungGut (einige Meter)Kurz (Board-intern)Sehr kurz (Board-intern)

Faustregeln:

  • UART, wenn Sie einfach zwei Geräte verbinden wollen oder zum PC kommunizieren müssen.
  • I2C, wenn Sie viele Sensoren oder Komponenten mit wenig Leitungen anbinden wollen.
  • SPI, wenn Sie hohe Geschwindigkeiten brauchen oder komplexe Peripherie wie SD-Karten ansteuern.

6. Erweiterungen und Derivate

Natürlich gibt es von diesen drei Grundprotokollen unzählige Varianten und Erweiterungen:

UART-Derivate:

  • RS-232: Die klassische PC-Schnittstelle mit höheren Spannungen (±12V) für größere Entfernungen.
  • RS-485: Differenzielle Übertragung für sehr lange Strecken und viele Teilnehmer in der Industrie.

I2C-Derivate:

  • SMBus (System Management Bus): Eine strenger spezifizierte Variante von I2C, oft in PC-Systemen.
  • PMBus: Für Stromversorgungen.

SPI-Derivate:

  • Quad-SPI: Nutzt mehrere Datenleitungen parallel für noch höhere Geschwindigkeit (bei Flash-Chips).
  • Microwire: Eine ältere, einfachere Variante von National Semiconductor.

7. Ein Praxisbeispiel: Sensordaten auslesen mit I2C

Stellen wir uns vor, wir wollen einen Temperatursensor (z.B. den berühmten LM75) über I2C auslesen. Der Sensor hat die Adresse 0x48 (typisch für viele I2C-Geräte).

Der Ablauf auf dem Bus:

  1. Master sendet START-Bedingung.
  2. Master sendet die 7-Bit-Adresse (0x48) plus ein Schreib-Bit (0).
  3. Sensor antwortet mit ACK (Acknowledge).
  4. Master sendet das Register, das er lesen will (z.B. 0x00 für Temperatur).
  5. Sensor antwortet mit ACK.
  6. Master sendet erneute START-Bedingung (Repeated Start).
  7. Master sendet die Adresse plus ein Lese-Bit (1).
  8. Sensor antwortet mit ACK und sendet dann die Temperaturdaten (2 Bytes).
  9. Master quittiert jedes Byte mit ACK, nach dem letzten mit NACK.
  10. Master sendet STOP-Bedingung.

In der Arduino-Welt reduziert sich das auf:

c

Wire.beginTransmission(0x48);
Wire.write(0x00);
Wire.endTransmission();
Wire.requestFrom(0x48, 2);
int temp = (Wire.read() << 8) | Wire.read();

Hinter diesen wenigen Zeilen verbirgt sich das gesamte Protokoll – die Bibliothek erledigt den Rest. Aber zu wissen, was da eigentlich passiert, hilft ungemein beim Debuggen, wenn mal etwas nicht funktioniert.

8. Fehlersuche im Protokoll-Dschungel

Wenn die Kommunikation nicht klappt, sind die häufigsten Fehler:

Bei UART:

  • Falsche Baudrate (die häufigste Fehlerquelle!)
  • TX und RX vertauscht
  • Falsche Pegel (3,3V vs. 5V)

Bei I2C:

  • Fehlende oder falsche Pull-up-Widerstände
  • Adresse falsch (oft 7-Bit vs. 8-Bit Verwirrung)
  • Zwei Geräte mit gleicher Adresse
  • Bus hängt durch ungültigen Zustand

Bei SPI:

  • Falsche Polarity/Phase (CPOL, CPHA) – das muss zum Slave passen
  • SS nicht richtig angesteuert
  • Leitungen vertauscht (MOSI mit MISO)

Ein Logikanalysator ist hier das Werkzeug der Wahl. Er zeigt die tatsächlichen Signale auf dem Bus und macht sichtbar, was wirklich passiert.


Fazit und Ausblick

UART, I2C und SPI sind die drei Säulen der lokalen Kommunikation in Embedded Systems. Jedes hat sein Einsatzgebiet, seine Stärken und Schwächen. Wer sie beherrscht, kann fast jedes Gerät an seinen Mikrocontroller anschließen.

Doch die Kommunikation ist nur ein Teil. Das Programm, das diese Kommunikation steuert, muss irgendwo laufen – und zwar oft ohne Betriebssystem, direkt auf der nackten Hardware.

Mit dieser Welt des „Bare-Metal“-Programmierens beschäftigen wir uns im nächsten Artikel.

Kommentar abschicken