Zum Inhalt springen

I2C vs. SPI: Wann nimmst du welchen Bus?

I2C und SPI im Vergleich: Leitungen, Geschwindigkeit, Adressierung, typische Fehler – und eine klare Entscheidungshilfe für dein nächstes Projekt.

Veröffentlicht:
Zuletzt aktualisiert:
5 Min. Lesezeit

Was unterscheidet I2C und SPI grundsätzlich?

Beide sind synchrone serielle Busse für kurze Distanzen auf der Leiterplatte, beide haben einen Master (Controller), der den Takt vorgibt. Danach hören die Gemeinsamkeiten auf.

Merkmal I2C SPI
Leitungen 2 (SDA, SCL), gemeinsam für alle Geräte 3 + 1 Chip-Select pro Gerät (SCLK, MOSI, MISO, CSn)
Adressierung 7-Bit-Adresse im Protokoll (bis 127 Geräte) Chip-Select-Leitung, keine Adresse
Richtung Halb-Duplex, eine Leitung für beide Richtungen Full-Duplex, Senden und Empfangen gleichzeitig
Typische Taktrate 100 kHz (Standard), 400 kHz (Fast), 1 MHz (Fast+), 3,4 MHz (High-Speed) 1 – 50 MHz, abhängig von Chip und Layout
Bestätigung ACK/NACK nach jedem Byte Keine – Fehler bleiben protokollseitig unsichtbar
Pull-up-Widerstände Erforderlich (Open-Drain) Nicht erforderlich (Push-Pull)
Multi-Master Im Standard vorgesehen (Arbitrierung) Nicht vorgesehen
Protokoll-Overhead Start, Adresse, ACK, Stop pro Transfer Praktisch keiner
Typische Geräte Temperatur-/Feuchtesensoren, EEPROMs, RTCs, IO-Expander, PMICs Displays, Flash-Speicher, SD-Karten, schnelle ADCs/DACs, Funkmodule

Wann ist I2C die richtige Wahl?

I2C glänzt, wenn Pins knapp und Datenmengen klein sind. Ein Temperatursensor liefert zwei Bytes alle 100 ms – dafür brauchst du keinen 20-MHz-Bus, aber du willst vielleicht acht solcher Sensoren an denselben zwei Leitungen hängen.

Weitere Argumente für I2C:

  • Weniger Leitungen auf der Platine, weniger Routing, weniger EMV-Fläche.
  • Standardisierte Adressierung: Geräte am selben Bus erkennst du per Scan (i2cdetect-Prinzip), was beim Bring-up hilft.
  • ACK/NACK gibt dir sofort Rückmeldung, ob ein Gerät antwortet – ein fehlendes ACK ist die beste Diagnose beim ersten Einschalten.
  • PMBus und SMBus bauen auf I2C auf; Netzteile, Batteriemanagement und Power-Sequencer sprechen fast ausschließlich diese Protokolle.

Die Kehrseite: I2C ist empfindlich gegenüber Layout und Pull-ups. Zu große Pull-ups verschleifen die Flanken (Clock-Stretching-Fehler, NACKs), zu kleine ziehen Strom. Lange Leitungen und mehrere Geräte erhöhen die Buskapazität – ab ca. 400 pF ist Schluss. Außerdem kann ein hängender Slave (SDA dauerhaft Low) den gesamten Bus blockieren; ein Treiber braucht dafür eine Bus-Recovery-Routine (neun Taktimpulse auf SCL).

Wann ist SPI die richtige Wahl?

SPI ist die Wahl, wenn Durchsatz zählt. Ein 320×240-Display mit 16 Bit Farbtiefe braucht pro Vollbild 150 KB – bei 400 kHz I2C wären das drei Sekunden, bei 40 MHz SPI 30 ms.

Weitere Argumente für SPI:

  • Full-Duplex und kein Protokoll-Overhead: Jeder Taktzyklus überträgt ein Bit in jede Richtung.
  • DMA-freundlich: Große Blöcke lassen sich ohne CPU-Beteiligung übertragen – entscheidend, wenn nebenbei ein RTOS laufen soll (wie sich Treiber-Tasks und Scheduler dann vertragen, erkläre ich in FreeRTOS Task-Prioritäten erklärt).
  • Einfache Hardware: Push-Pull-Treiber, keine Pull-ups, robuste Flanken auch bei längeren Leitungen.
  • Deterministisch: Kein Clock-Stretching, kein Arbitrierungs-Verlust – der Master bestimmt das Timing vollständig.

Die Kehrseite: Ein Chip-Select pro Gerät – bei fünf Geräten sind das fünf zusätzliche GPIOs (oder ein IO-Expander, der dann wieder über I2C hängt). Es gibt keine Fehlerrückmeldung im Protokoll; ob ein Gerät überhaupt angeschlossen ist, erkennst du nur über ein ID-Register. Und die vier SPI-Modi (CPOL/CPHA) sind eine klassische Fehlerquelle: Stimmt der Modus nicht mit dem Datenblatt überein, bekommst du verschobene oder invertierte Bits – ohne Fehlermeldung.

Wie sieht ein minimaler Treiber-Aufruf jeweils aus?

Der Unterschied zeigt sich auch im Code. Hier ein Register-Lesezugriff auf einen Sensor – einmal über I2C, einmal über SPI – jeweils gegen eine schlanke HAL-Schnittstelle, wie wir sie im Praxiskurs Embedded C & FreeRTOS aufbauen:

/* I2C: Register-Adresse schreiben, dann Daten lesen (Repeated Start) */
bsp_status_t tmp117_read_temp(i2c_bus_t *bus, uint8_t addr, int16_t *raw)
{
    uint8_t reg = TMP117_REG_TEMP;
    uint8_t buf[2];

    bsp_status_t st = i2c_write_read(bus, addr, &reg, 1, buf, 2, I2C_TIMEOUT_MS);
    if (st != BSP_OK) {
        return st;            /* NACK, Timeout oder Bus-Fehler */
    }
    *raw = (int16_t)((buf[0] << 8) | buf[1]);
    return BSP_OK;
}

/* SPI: Chip-Select aktiv, Kommando + Dummy-Byte, Antwort kommt parallel */
bsp_status_t bme280_read_id(spi_bus_t *bus, gpio_t cs, uint8_t *id)
{
    uint8_t tx[2] = { BME280_REG_ID | 0x80u, 0x00u };   /* Bit 7 = Lesen */
    uint8_t rx[2];

    gpio_write(cs, 0);
    bsp_status_t st = spi_transfer(bus, tx, rx, sizeof tx, SPI_TIMEOUT_MS);
    gpio_write(cs, 1);

    if (st != BSP_OK) {
        return st;
    }
    *id = rx[1];              /* erstes Byte ist Dummy während des Kommandos */
    return BSP_OK;
}

Beachte: Der I2C-Treiber bekommt einen Fehler vom Bus zurück, wenn der Sensor nicht antwortet. Der SPI-Treiber liefert bei fehlendem Sensor einfach 0xFF oder 0x00 – deshalb liest man bei SPI-Geräten beim Bring-up immer zuerst das ID-Register und vergleicht es mit dem Datenblatt.

Welche Fehler passieren in der Praxis am häufigsten?

Symptom Bus Wahrscheinliche Ursache Prüfung
Kein ACK, Gerät „nicht gefunden“ I2C Falsche Adresse (7-Bit vs. 8-Bit-Schreibweise), fehlende Pull-ups, Gerät ohne Versorgung Adresse im Datenblatt prüfen, SDA/SCL mit Oszilloskop: High-Pegel erreicht?
Sporadische NACKs bei hoher Last I2C Pull-ups zu groß, Buskapazität zu hoch Flanken anschauen: Anstiegszeit < 300 ns (Fast-Mode)
Bus dauerhaft blockiert I2C Slave hängt mit SDA Low nach Reset mitten im Transfer Bus-Recovery (9 Clock-Pulse) im Init
Daten um ein Bit verschoben SPI Falscher Modus (CPOL/CPHA) Datenblatt: „data captured on rising edge“ → Modus 0 oder 3
Immer 0xFF oder 0x00 SPI MISO nicht verbunden, CS nicht aktiv, Gerät ohne Versorgung ID-Register lesen, CS-Leitung mit Logic Analyzer prüfen
Erstes Byte richtig, Rest Müll SPI Taktrate zu hoch für Leitungslänge oder Chip Takt halbieren, Datenblatt-Maximum prüfen

Entscheidungshilfe in drei Fragen

  1. Wie viele Bytes pro Sekunde? Unter ~20 KB/s: I2C ist ausreichend. Darüber: SPI.
  2. Wie viele Geräte, wie viele freie Pins? Viele Geräte, wenige Pins: I2C. Wenige Geräte, Pins vorhanden: SPI.
  3. Was bietet der Chip an? Viele Sensoren unterstützen beides – dann entscheidet die Frage, ob du den Bus mit anderen Geräten teilst (I2C) oder ihn für ein Gerät exklusiv mit DMA betreiben willst (SPI).

In realen Geräten findest du fast immer beide: I2C für die Sensorik und das Power-Management, SPI für Flash, Display und schnelle Wandler. Ein sauber geschichteter Treiber-Aufbau macht es egal, welcher Bus unter einem Sensor liegt – die Applikationsschicht ruft sensor_read() auf und muss den Unterschied nicht kennen.

  • I2C
  • SPI
  • Peripherie
  • Treiber
  • Embedded C
Porträt von Gaëtan Pandji

Gaëtan Pandji

Senior Embedded Software Engineer

Gaëtan Pandji ist Senior Embedded Software Engineer (M.Sc. Elektrotechnik, TU Darmstadt) mit über vier Jahren Industrieerfahrung in Firmware-Entwicklung, FreeRTOS, Embedded Linux (Yocto) und OPC UA – u. a. bei Schneider Electric, Hilscher und Muegge. Nebenberuflich unterrichtet er Python und C++ und gibt bei Tesdyne Praxiswissen für Embedded-Einsteiger und Umsteiger weiter.

FreeRTOS-Checkliste: 12 Fehler, die Embedded-Einsteiger machen

Ein PDF, das du neben dein nächstes Projekt legst. Jeder Punkt mit Symptom, Ursache und Lösung – aus echten Code-Reviews.

Double-Opt-in: Du bekommst zuerst eine Bestätigungs-E-Mail. Erst nach deinem Klick auf den Bestätigungslink wird die Checkliste verschickt.

  • Kein Spam, Abmeldung mit einem Klick
  • Double-Opt-in, DSGVO-konform
  • Keine Cookies auf dieser Seite

← Zurück zum Blog