Table of Contents
Einführung in I2C und SPI mit PIC Microcontrollern
Mikrocontroller aus der PIC-Familie von Microchip werden in eingebetteten Systemen weit verbreitet eingesetzt, von einfachen Sensorknoten bis hin zu komplexen industriellen Controllern. Eine Schlüsselkompetenz für jeden Embedded-Entwickler ist die Fähigkeit, Peripheriegeräte mit seriellen Kommunikationsprotokollen zu verbinden. Zwei der häufigsten sind I2C (Inter-Integrated Circuit) und SPI (Serial Peripheral Interface).
Dieser Artikel bietet eine praktische, ausführliche Anleitung zur Implementierung von I2C und SPI auf PIC-Mikrocontrollern. Wir werden Hardware-Einrichtung, Registerkonfiguration, typische Codesequenzen und gängige Debugging-Techniken behandeln. Am Ende haben Sie das Wissen, um Ihrem nächsten PIC-Projekt sicher serielle Kommunikation hinzuzufügen.
Übersicht über I2C und SPI
Beide Protokolle sind synchrone serielle Busse, unterscheiden sich jedoch in Architektur, Geschwindigkeit und Anwendung.
I2C (Inter-Integrated Circuit)
I2C verwendet nur zwei Leitungen: SDA (Serial Data) und SCL (Serial Clock). Jedes Gerät auf dem Bus hat eine eindeutige 7-Bit- oder 10-Bit-Adresse, und die Kommunikation ist Master-Slave. Der Master generiert die Uhr und initiiert Transaktionen. Mehrere Master können den Bus mit Arbitrierung teilen. Der Standardmodus läuft bei 100 kHz, der schnelle Modus bei 400 kHz und der Hochgeschwindigkeitsmodus bis zu 3,4 MHz. I2C ist ideal für Peripheriegeräte, die keine lodernde Geschwindigkeit erfordern, wie Temperatursensoren, Echtzeituhren, EEPROMs und kleine Displays.
Da nur zwei Drähte benötigt werden, speichert I2C I/O-Pins, was es für kleine PICs attraktiv macht. Das Protokoll ist jedoch komplexer als SPI, da es Adressierung, Acknowledge Bits und Clock Stretching betrifft.
SPI (Serial Peripheral Interface)
SPI verwendet vier Zeilen: MOSI (Master Out Slave In), MISO (Master In Slave Out), SCLK (Slave Select). Es ist ein Vollduplexbus – Daten werden gleichzeitig gesendet und empfangen. Der Master generiert die Uhr und wählt den Slave aus, indem er seinen Chip-Select (SS)-Pin niedrig zieht. SPI ist deutlich schneller als I2C mit Geschwindigkeiten in Zehn MHz und ist das Protokoll der Wahl für Hochdurchsatzgeräte wie SD-Karten, grafische Displays, ADCs und digitale Potentiometer.
SPI ist einfacher in Hardware zu implementieren, erfordert aber mehr Pins – eine dedizierte SS-Linie pro Slave. Viele PIC-Mikrocontroller verfügen über ein dediziertes Master Synchronous Serial Port (MSSP) Modul, das entweder für I2C oder SPI konfiguriert werden kann.
Hardware-Betrachtungen für I2C und SPI
Bevor Sie in Code eintauchen, müssen Sie die Hardware richtig machen.
Pull-up-Widerstände: I2C-Leitungen sind Open-Drain; sie erfordern externe Pull-up-Widerstände (normalerweise 4,7 kΩ bis 10 kΩ), um SDA und SCL nach VDD zu ziehen. Der Wert hängt von der Buskapazität und -geschwindigkeit ab. Für lange Busse oder schnellen Modus können niedrigere Widerstandswerte erforderlich sein, um die Anstiegszeitspezifikationen zu erfüllen.
Spannungspegel: Stellen Sie sicher, dass Ihr PIC und die Peripherie mit der gleichen Logikspannung arbeiten (z. B. 3,3 V oder 5 V). Wenn sie sich unterscheiden, verwenden Sie Pegelschieber wie den SparkFun BOB-12009 oder eine einfache MOSFET-Schaltung.
Buslänge und kapazitive Belastung: Halten Sie die Buskapazität für längere Leitungen (über ein paar Zoll) unter dem in Ihrem PIC-Datenblatt angegebenen Maximum (PIC16F1xxx-Datenblatt oft 400 pF für I2C. Für SPI können längere Leitungen Signalreflexionen verursachen; verwenden Sie bei Bedarf langsamere Taktraten und abgeschirmte Kabel.
Decoupling capacitors: Platziere 0.1 μF-Kondensatoren in der Nähe der Power-Pins jedes ICs, um Rauschen zu unterdrücken, das Daten korrumpieren kann.
Konfiguration von I2C auf PIC-Mikrocontrollern
Die meisten modernen PICs beinhalten das Master Synchronous Serial Port (MSSP) Modul, das sowohl I2C als auch SPI unterstützt. Wir werden uns auf das MSSP im I2C Master-Modus für ein typisches 8-Bit-PIC (z. B. PIC16F18877) konzentrieren.
Schlüsselregister für I2C
- SSPxADD – Baud Rate Generator Reload-Wert. Die I2C-Taktfrequenz wird aus dem Systemtakt mit einer Formel abgeleitet: FSCL = FOSC / (4 * (SSPxADD + 1)).
- SSPxSTAT – Statusregister. Bits zeigen Buskollision an, schreiben Kollision und ob eine Start-/Stopp-Bedingung erkannt wurde.
- SSPxCON1 – Kontrollregister 1. Wählen Sie den I2C-Modus (Master, Slave) und aktivieren Sie das Modul.
- SSPxCON2 – Master-Modussteuerung. Befehle zum Senden von Start, Neustart, Stop und Quittung.
- SSPxBUF – Datenpuffer.
I2C Master Initialisierungssequenz
- Deaktivieren Sie das MSSP-Modul, indem Sie das Bit SSPEN löschen (SSPxCON1<5>).
- I2C-Master-Modus einstellen (normalerweise 0x08 in SSPxCON1-Bits <3:0>).
- Konfigurieren Sie die Baudrate, indem Sie SSPxADD mit dem richtigen Wert laden.
- Setzen Sie SDA- und SCL-Pins als Eingänge mit schwachen Pull-ups ein (oder verwenden Sie externe Widerstände).
- Aktivieren Sie das Modul, indem Sie SSPEN festlegen.
- Optional Interrupts für den MSSP aktivieren.
Beispiel: Ablesen von einem LM75 Temperatursensor
Der LM75 hat eine 7-Bit-Adresse (typischerweise 0x48 für die geerdeten A0-A2-Pins), um das Temperaturregister (Pointer 0x00) zu lesen, muss man zunächst den Zeiger schreiben, dann einen wiederholten Start erzeugen und lesen.
Write pointer sequence: Start → address byte (0x90) → wait for ACK → pointer byte (0x00) → wait for ACK → Stop.
Read temperature sequence: Start → address byte (0x91) → wait for ACK → read two bytes (MSB, LSB) → NACK on last byte → Stop
Jeder Byteaustausch erfordert das Abfragen des SSPxSTAT-Registers für das BF-Bit (Buffer Full) und das SSPxIF-Interrupt-Flag. Ein häufiger Fehler ist das Vergessen, das ACK/NACK nach dem Empfang von Daten zu senden. Verwenden Sie die ACKDT und ACKEN Bits in SSPxCON2, um die Quittierung zu steuern.
I2C-Fallfallen
- Clock stretching: Einige Slaves halten SCL niedrig, um den Master zu verlangsamen. Aktivieren Sie die Unterstützung für Clock Stretching im MSSP (setzen Sie das CKP Bit entsprechend ein).
- Bus-Kollision: Wenn ein anderer Master versucht, den Bus zu fahren, setzt der MSSP das BCLIF-Flag.
- Stuck bus: Wenn ein Slave SDA nach einer Übertragung nicht freigibt, kann der Bus hängen bleiben. Implementieren Sie ein Timeout, das neun Taktimpulse sendet, um sich zu erholen.
Konfiguration von SPI auf PIC-Mikrocontrollern
Der MSSP kann auch im SPI-Master- oder Slave-Modus arbeiten.
Schlüsselregister für SPI
- SPIxBRG – Baud Rate Generator. Für SPI ist die Taktfrequenz FOSC / (2 * (SPIxBRG + 1)).
- SPIxSTAT – Statusregister. Enthält das BF-Bit, Schreibkollision, Überlauf-Flags empfangen.
- SPIxCON1 – Kontrollregister 1. Wählt Master/Slave, Taktpolarität (CKP), Taktphase (CKE) und Abtastpunkt (SMP) aus.
- SPIxCON2 – Zusätzliche Steuerung (z.B. Frame Mode, SS2 enable).
- SPIxBUF – Datenpuffer zum Senden und Empfangen (gepuffert).
SPI Master Initialisierungssequenz
- Deaktivieren Sie das SPI-Modul (Clear SSPEN).
- Stellen Sie die gewünschte Taktpolarität und Phase ein. Mode 0 (CKP=0, CKE=1) ist am häufigsten: Daten werden an der steigenden Flanke abgetastet und an der fallenden Flanke verschoben.
- Konfigurieren Sie die Baudrate in SPIxBRG. Für 1 MHz mit einer 16 MHz-Takt, SPIxBRG = 7.
- Hauptmodus auswählen (SSPM-Bits = 0b0000 für SPI-Master, Uhr = FOSC/4).
- Setzen Sie die SS-Pin-Richtung. Bei vielen PICs ist der SS-Pin eine dedizierte Eingabe im Master-Modus. Für die Slave-Auswahl müssen Sie einen separaten GPIO-Pin umschalten, der mit dem Chip-Select des Slaves verbunden ist.
- Aktivieren Sie das Modul.
Beispiel: Schnittstelle mit einem MCP3008 8-Kanal-ADC
Der MCP3008 ist ein 10-Bit-ADC, der über SPI im Modus 0 kommuniziert. Zum Lesen eines Kanals (z.B. Kanal 0) sendet der Master drei Bytes: ein Startbit, ein Single-ended/Differential-Bit und die Kanaladresse. Der Slave gibt gleichzeitig zwei Datenbytes zurück.
Transaktionssequenz:
1. Drive SS low.
2. Write 0x01 (start bit) to SPIxBUF – wait for BF bit to clear.
3. Write (channel | 0x80) to SPIxBUF – read the first waste byte from the previous transfer.
4. Write 0x00 (dummy) to SPIxBUF – read the high 8 bits of conversion result.
5. Write 0x00 again – read the low 2 bits and trailing zeros.
6. Drive SS high.
Beachten Sie, dass jeder Schreibvorgang an SPIxBUF einen gleichzeitigen Empfang auslöst.
Verwalten mehrerer SPI-Slaves
Jeder Slave benötigt einen eindeutigen Chip-Select-Pin. Verwenden Sie einen GPIO pro Slave. Stellen Sie sicher, dass es eine kleine Verzögerung zwischen dem Wechsel des SS-Pins und dem Starten der Uhr gibt, um die Setup-Zeitanforderungen des Slaves zu erfüllen. Viele PICs ermöglichen es Ihnen, den Hardware-SS-Pin für die automatische Slave-Select-Generierung nur im Slave-Modus zu verwenden; im Master-Modus müssen Sie dies manuell tun.
Debugging von I2C und SPI Kommunikation
Wenn die Dinge nicht funktionieren, folgen Sie einem methodischen Ansatz:
- Verwenden Sie einen Logikanalysator oder ein Oszilloskop. Dies ist das effektivste Debugging-Tool. Überprüfen Sie, ob die Uhr vorhanden ist, Datenübergänge auftreten und die Adressen korrekt sind.
- Überprüfen Sie Pull-up-Widerstände. Wenn SDA oder SCL niedrig bleiben, haben Sie möglicherweise ein Gerät, das den Bus hält. Trennen Sie alle Slaves bis auf einen und versuchen Sie es erneut.
- Verifizieren Sie die Baudrate. Messen Sie das Taktsignal mit einem Anwendungsbereich. Für I2C muss die Taktfrequenz innerhalb der Spezifikation des Slaves liegen.
- Adresse und Befehlsbytes untersuchen. Ein häufiger Fehler ist das Senden einer 7-Bit-Adresse, ohne um eins nach links zu verschieben (das R/W-Bit geht in LSB).
- Für SPI überprüfen Sie die Polarität und Phase der Uhren. Viele Slaves sind empfindlich auf den genauen Modus. Lesen Sie das Datenblatt des Slaves. Stellen Sie außerdem sicher, dass die Chip-Select-Linie niedrig aktiv ist und entsprechend angesteuert wird.
Wenn das Hardware-Debugging korrekte Wellenformen anzeigt, liegt das Problem möglicherweise in Ihrer Firmware. Verwenden Sie Debug-LEDs oder eine serielle Konsole, um Statusregister auszudrucken. Viele PIC-Entwicklungsboards enthalten einen On-Board-Programmierer/Debugger (z. B. MPLAB PICkit 4), der Ihnen helfen kann, den Code zu durchlaufen.
Software Bit‐Banging als Backup
Wenn die Hardware-Peripherie nicht verfügbar ist oder wenn Sie einen PIC verwenden müssen, der keinen MSSP hat, können Sie I2C oder SPI in Software mit GPIO-Pins implementieren. Für I2C-Bit-Banging schalten Sie SDA und SCL direkt um, was Zeitverzögerungen berücksichtigt. Für SPI verschieben Sie Bits durch einen GPIO und lesen gleichzeitig den Eingangspin aus. Bit-Banging ist flexibel, verbraucht jedoch CPU-Zyklen und ist langsamer. Es ist auch eine gute Möglichkeit, das Protokoll auf einem niedrigen Niveau zu lernen.
Fortgeschrittene Themen
I2C Multi-Master und Clock Speed Tuning
Wenn sich mehrere Master den Bus teilen, müssen Sie die Arbitrierung sorgfältig behandeln. Der MSSP im PIC unterstützt den Multi-Master-Modus; er überwacht den Bus und gibt die Kontrolle auf, wenn ein anderer Master Daten sendet. Verwenden Sie den Bus-Kollisionsunterbruch (BCLIF), um den Verlust der Arbitrierung zu erkennen und nach einer zufälligen Verzögerung erneut zu versuchen.
Für schnellere I2C (z. B. 400 kHz) ermöglichen Sie eine Slew-Rate-Steuerung an den Ausgangspins (falls verfügbar) und verwenden Sie stärkere Pull-up-Widerstände (z. B. 2,2 kΩ). Einige PICs haben einen dedizierten SSPxADD, der mit einem Vorskalierer auf Werte kleiner als Null eingestellt werden kann.
SPI Daisy‐Chaining und DMA
Einige SPI-Geräte unterstützen Daisy-Chaining, wobei der Datenausgang (MISO) eines Geräts den Eingang (MOSI) des nächsten Geräts speist. Dies ermöglicht mehrere Slaves mit einer einzigen Chip-Select-Linie. Das MSSP kann Daisy-Chaining handhaben, wenn die Geräte es unterstützen.
Für High-Speed-SPI sollten Sie den Direct Memory Access (DMA) Controller des PIC in Betracht ziehen (der bei vielen neueren PICs verfügbar ist). DMA kann Daten ohne CPU-Eingriff zum/vom SPI-Puffer übertragen und den Kern für andere Aufgaben freigeben. Die DMA-Peripherie wird mit Quelle, Ziel und Zählung konfiguriert und dann durch den SPI-Interrupt ausgelöst.
Schlussfolgerung
I2C und SPI sind wesentliche Werkzeuge in jedem Embedded-Designer-Kit. Mit dem flexiblen MSSP-Modul, das in den meisten PIC-Mikrocontrollern zu finden ist, ist die Implementierung dieser Protokolle einfach, sobald Sie die Register-Einrichtung und die Zeitparameter verstanden haben. Beginnen Sie immer mit einem einfachen Test - einer Dummy-Schreib-/Leseschleife -, um Ihre Hardware- und Software-Grundlage zu überprüfen.
Datenblätter bleiben Ihr bester Freund: Die offiziellen Datenblätter von Mikrochips liefern genaue Registerkarten und Zeitdiagramme. Anwendungshinweise wie AN734 (I2C-Tipps) und AN1009 (SPI-Nutzung) sind wertvolle Ressourcen. Üben Sie mit einem Entwicklungsboard und einem Logikanalysator, und Sie werden schnell Vertrauen gewinnen, wenn Sie I2C oder SPI-Peripherie zu Ihren PIC-basierten Projekten hinzufügen.