Dieses Tutorial, das ich auf der Embedded Linux-Konferenz gegeben habe, versucht, die Fragen zu beantworten. Es enthält Links zu einer detaillierteren Beschreibung der behandelten Themen und verwendet das praktische Beispiel für das Fahren einer 4WD-Drohne, bei der ein Arduino Mini Pro als Slave fungiert und die 4 unabhängigen Räder steuert . Das Originaldokument finden Sie hier .
Hinweis: Diese Antwort ist derzeit in Arbeit, da ich die Highlights aus dem Link anpasse.
Typische Anwendungen des I2C-Busses
- Schnittstelle zu relativ langsamen Peripheriegeräten. Bsp.: Sensoren, mechanische Aktuatoren.
Steuerung „schneller“ Peripheriegeräte, die andere Kanäle für den Datenaustausch verwenden. Beispiel: Codecs.
In einem PC interagiert das Betriebssystem normalerweise über I2C mit:
- Temperatur- und Batteriespannungsmesser;
- Lüfterdrehzahlregler;
- Audio-Codecs.
Wenn mehrere Buscontroller verfügbar sind, werden Peripheriegeräte nach Geschwindigkeit gruppiert, sodass schnelle nicht durch langsamere bestraft werden.
Eine kurze Einführung in die wichtigsten Funktionen des I2C-Busses
- Serien Bus.
- Nur 2 Leitungen: Serial CLock und Serial DAta (plus Masse).
- 4 Geschwindigkeiten: 100 kHz, 400 kHz, 1 MHz, 3,2 MHz.
- Normalerweise 1 Master-Gerät und 1 oder mehr Slaves.
- Die Kommunikation wird immer von einem Master-Gerät initiiert.
- Auf demselben Bus können mehrere Master nebeneinander existieren (Multi-Master).
- Open-Drain: Sowohl SDA als auch SCL benötigen Pull-up-Widerstände.
- "Clock Stretching"
- Der Master steuert SCL, aber ein Slave kann es gedrückt halten (weil offener Drain), wenn er die Geschwindigkeit anpassen muss.
- Der Master muss nach diesem Szenario suchen.
- Ein Slave kann stecken bleiben und den Bus blockieren: Es müssen Leitungen vom Master zum Slave zurückgesetzt werden.
- In der Regel wird eine 7-Bit-Adressierung, aber auch eine 10-Bit-Adressierung unterstützt.
- Logisches Protokoll: Die tatsächlichen Spannungspegel sind nicht angegeben und hängen von den einzelnen Implementierungen ab. Beispiel: 1,8 V / 3,3 V / 5,0 V.
Referenz-URLs:
Beispiel für eine Buskonfiguration
Merkmale des Protokolls (vereinfacht)
- 2 Nachrichtentypen: Lesen und Schreiben
- Start / Stopp-Bit - wird im Rest der Antwort als "[" und "]" dargestellt
- Adresse: 7 oder 10 Bit
- R / W-Bit: R = 1 / W = 0 Wird verwendet, um den Typ der gesendeten Nachricht zu unterscheiden.
- Daten auf dem Bus: (Adresse << 1 | R / W)
- Registriert sich als Informationshandler innerhalb des ausgewählten Geräts.
Beispiel für Busverkehr
Benutzerdefinierte Slaves
Warum einen benutzerdefinierten I2C-Slave erstellen?
- Gewünschter Sensor / Aktor mit I2C-Schnittstelle nicht verfügbar.
- Es sind weniger eindeutige Adressen verfügbar als für Slaves erforderlich.
- Gewünschte benutzerdefinierte Funktionalität auf dem Slave:
- Halbautonome Reaktionen auf Reize.
- Eingabedaten filtern / vorverarbeiten.
- Leistungsoptimierung: Der benutzerdefinierte „Sensor-Hub“ übernimmt die Haushaltsführung, während der Hauptprozessor im Leerlauf ist.
- Echtzeitantwort auf Eingaben.
- [deine Fantasie hier]
Wie entwerfe ich einen benutzerdefinierten I2C-Slave?
- Anforderungen definieren (siehe vorherige Folie).
- Wählen Sie einen Mikrocontroller oder einen Mikroprozessor.
- Wählen Sie Scheduler oder Betriebssystem (falls vorhanden).
- Kommunikationsunterprotokoll definieren:
- Definieren Sie die auszutauschenden Parameter und Befehle.
- Organisieren Sie sie in „Registern“ und wählen Sie eine freie Adresse.
Design des I2C-Masters
Wichtige Designkriterien:
- Gewicht / Abmessungen.
- Erforderliche Rechenleistung und durchschnittliche Latenz.
- PC-ähnliches Gerät
- Eingebettetes Gerät, normalerweise ohne Kopf.
- Bevorzugte Programmiersprache: interpretiert oder kompiliert.
- Verfügbarkeit von Bussen / GPios zum Fahren der Slaves:
- Nur GPIOs: Bitbang das Protokoll
- I2C: User-Space-Anwendung gegen Kerneltreiber.
- Keine GPIOs / I2C-Schnittstellen verfügbar: USB-zu-I2C-Adapter.
Debuggen: Teilen und Erobern
Übernehmen Sie die direkte Kontrolle über den Bus mit einem Ad-hoc-Gerät. Beispiele:
Bus Pirat
- Hauptsächlich für Entwicklungszwecke.
- Kann sowohl den Bus schnüffeln als auch fahren.
- Konsolenschnittstelle über seriellen (ttyACM) Port, einschließlich Makros, oder programmgesteuerten Zugriff für mehrere Programmiersprachen.
- Eingebaute Pullup-Widerstände und Spannungsquellen (5V / 3,3V)
- Unterstützt viele andere Protokolle.
- Referenzen: Wikipedia , Hauptseite
USB zu I2C Adapter
- Kleiner Fußabdruck.
- Geeignet für dauerhafte Installationen.
- Keine speziellen Verbindungen auf dem Host erforderlich: Es kann zur Schnittstelle mit einem typischen PC verwendet werden.
- Variante erhältlich, die auch SPI-fähig ist.
- Keine Konsolenschnittstelle, nur serielles Binärprotokoll.
- Erfordert einen Protokoll-Wrapper .
- Referenz: Protokoll
Sigrok und Pulsview
Sigrok-Logo (Bakend-Komponente)
Beispiel für die Pulsansicht (Visualizer)
Beispiel eines Low-End-Logikanalysators
- De-facto-Standard für PC-gesteuerte Messungen unter Linux (aber auch unter anderen Betriebssystemen verfügbar).
- Unterstützung für eine Vielzahl von Logikanalysatoren, Oszilloskopen und Messgeräten.
- Verschiedene Protokolldecoder, einschließlich I2C.
- Nützlich zur Visualisierung der logischen Signale und zum Debuggen von Protokollfehlern.
- Selbst sehr kostengünstiges HW kann dem Debuggen eine völlig neue Dimension verleihen.
- Referenzen: Sigrok , Pulsview , unterstützte Hardware
Beispiel: Steuern einer 4WD-Drohne
Prototyp gebaut mit 2 Arduino Mini Pro.
Was macht der Sklave im Beispiel?
Der I2C-Slave:
- Steuert das auf jedes Rad ausgeübte Drehmoment.
- Steuert die Richtung, in die sich jedes Rad dreht.
- Misst die Drehzahl jedes Rades über einen optischen Encoder (Kilometerzähler).
- Stellt die oben genannten Parameter dem I2C-Master zur Verfügung.
Hochrangiges Blockdiagramm des I2C-Slaves.
- Genug Stifte / Funktionen für jedes Rad:
- 1 PWM-Ausgang mit unabhängiger Konfiguration des Arbeitszyklus.
- 1 GPIO zur Registrierung des Kilometerzählereingangs als IRQ.
- 2 GPIOs zur Auswahl:
- Nach vorne
- Umkehren
- Leerlauf
- Sperren
- I2C HW-Block für Interrupt-gesteuerte i2c-Austausche.
- Spezielle Pins für die SPI-basierte Programmierung.
- Kleiner Fußabdruck.
- Kostengünstig.
- Das Board-Layout des im Bild dargestellten Klons ist für die Montage an einer DIL-Buchse optimiert.
Slave-spezifischer ICD: AVR Dragon
Auswählen des Betriebssystems: ChibiOS
- RTOS: Preemption, Aufgaben, Semaphoren, dynamischer System-Tic usw.
- Geringer Platzbedarf: Nur verwendeten Code / Daten verknüpfen.
- Unterscheidung zwischen RTOS und BSP durch HAL.
- GPLv3 für nichtkommerzielle Zwecke.
- Aktiv entwickelt, aber schon ausgereift.
- Unterstützt 8bit AVR.
Es gab jedoch eine eingeschränkte BSP-Unterstützung für AVR, das Fehlen von: - Interrupt-Treiber für AVR-GPIOs (hinzugefügt). - I2C-Unterstützung für den AVR-Slave-Modus (benutzerdefiniert). Was im Rahmen der Drone SW für den AVR separat entwickelt werden musste .
Kommunikationsparameter definieren
Für jedes Rad:
Arbeitszyklus des PWM-Signals, mit dem es angesteuert wurde - 1 Byte. 0xFF = maximales Drehmoment / 0x00 = kein Drehmoment.
Richtung Dreh - 1 Byte.
- 0x00 = Leerlauf
- 0x01 = umgekehrt
- 0x02 = vorwärts
- 0x03 = gesperrt
Durchschnittliche Zeitspanne zwischen den Steckplätzen des optischen Codierers - 2 Bytes.
- Wenn Sie etwas schreiben, wird die Messung zurückgesetzt.
Parameter Index - 1 Knabbern:
- 0 = Arbeitszyklus
- 1 = Richtung
- 2 = Durchschnittlicher Zeitraum
Radindizes - 1 Knabberzeug:
- 0 = Links hinten
- 1 = rechts hinten
- 2 = Rechts vorne
- 3 = Links vorne
- 4 = Alle
Unterprotokoll: Definieren der Register
Registerformat: 0xαβ
- α = Parameterindex - β = Radindex
Adresse (willkürlich gewählt): 0x10
Buspiratenformat:
- [= Startbit -] = Endbit - r = Lesebyte - Adresszeiten 2 (Linksverschiebung 1) für R / W-Bit
Beispiel - im Buspiratenformat
[i2c_addr reg_addr = (Parameter, Rad) reg_value]
[0x20 0x20 0x02] Left Rear Forward
[0x20 0x21 0x01] Right Rear Backward
[0x20 0x22 0x01] Right Front Backward
[0x20 0x23 0x02] Left Front Forward
[0x20 0x14 0xFF] Wheels set to max torque
Das Auto dreht sich im Uhrzeigersinn.