Two Wire Interface
Worum geht's?
[Bearbeiten]Über den TWI Bus können bis zu 120 externe Geräte mit dem dem Microcontroller verbunden werden.[1] Da der TWI Bus nur aus zwei Leitungen besteht, werden dabei nur 2 Pins des Microcontrollers benötigt.
Einige Microcontroller der AVR Familie verfügen über eine Funktionseinheit, die es ermöglicht, den Microcontroller über zwei für diesen Zweck vorgesehene Pins am TWI Bus zu betreiben. Die Geschwindigkeitsanforderungen an den TWI Bus sind so gering, dass auch ein Microcontroller ohne TWI Funktionseinheit mit einer Software Lösung am TWI Bus betreiben werden kann. Um diese Möglichkeit wird es allerdings erst im folgenden Kapitel gehen.
In diesem Kapitel werden wir ausschließlich mit der integrierten TWI Funktionseinheit arbeiten. Kenntnis der in diesem Kapitel vorgestellten Konzepte und Begriffe, sowie ein grundlegendes Verständnis der prinzipiellen Arbeitsweise des TWI Bus sind über dieses Kapitel hinaus auch für die Implementierung einer Software Lösung wichtig.
Auch wenn Dein Microcontroller über keine integrierte Funktionseinheit verfügt, Du aber an der Software Lösung des folgenden Kapitels interessiert bist, solltest Du Dich zumindest grob mit dem Inhalt dieses Kapitels vertraut machen.
Folgende Dinge kannst Du in diesem Kapitel lernen:
- für die TWI Funktionseinheit vorgesehene Pins lokalisieren
- externe Geräte über den TWI Bus mit dem Microcontroller verbinden
- wichtige Begriffe und Konzepte des TWI Bus
- Schritte und Ablauf des am TWI Bus eingesetzten Protokolls
- den Microcontroller als TWI Bus Master konfigurieren
- im synchronen Master Betrieb Daten zwischen Microcontroller externen Geräten übertragen
Grundlagen
[Bearbeiten]Der TWI Bus (Two Wire Bus) läuft auch unter dem Namen I²C Bus.
Um einen AVR Microcontroller mit integrierter TWI Funktionseinheit am TWI Bus zu betreiben, wird keine umfangreiche Kenntnis der genauen elektrischen Eigenschaften des TWI Bus benötigt. Mit den elektrischen Eigenschaften werden wir uns daher erst im nächsten Kapitel beschäftigen und eine genaue Beschreibung nachliefern.
In diesem Kapitel werden wir den TWI Bus zunächst als eine Black-Box betrachten, mit deren Hilfe der Microcontroller mit anderen, für einen Betrieb am TWI Bus vorgesehenen Geräten Daten austauschen kann.
Leitungen und Anschluss
[Bearbeiten]Der TWI Bus ist ein serieller Bus. Daten, die über den TWI Bus transportiert werden, werden sequentiell ein Bit nach dem anderen übertragen. Für die Übertragung werden nur zwei Leitungen benötigt.
Eine der beiden Leitungen dient der Übertragung der einzelnen Datenbits. Sie wird daher auch als Datenleitung oder kurz SDA (Serial DAta) bezeichnet. Die zweite Leitung dient der Synchronisation. Über sie wird geregelt, welches Gerät zu welchem Zeitpunkt Daten auf den Datenleitung legen, bzw. sie von dort entnehmen darf. Die Synchronisation erfolgt mit einem Taktsignal. Die zweite Leitung wird daher auch als Taktleitung oder kurz SCL (Serial CLock) bezeichnet.
Damit die Kommunikation über den TWI Bus funktioniert, müssen beim Anschließen eines Geräts die richtigen Leitungen miteinander verbunden werden. Der SDA Pin muss immer an die SDA Leitung und der SCL Pin immer an die SCL Leitung angeschlossen werden. Beim Anschluss an den TWI Bus findet kein Überkreuzen der Leitungen, wie Du es vielleicht von RX und TX bei der seriellen Schnittstelle kennst, statt.
Das Datenblatt des Geräts, dass Du anschließen möchtest, sollte Auskunft darüber geben, an welcher Stelle SDA Leitung und SCL Leitung angeschlossen werden müssen. In vielen Fällen findet sich zusätzlich eine entsprechende Beschriftung am Gerät selbst.
Slave und Slave Adresse
[Bearbeiten]Ein Gerät, das über den TWI Bus angesprochen werden kann, wird auch Slave genannt.
Jeder Slave verfügt über eine 7-Bit lange Adresse, mit der er identifiziert werden kann. Diese Adresse wird auch Slave-Adresse des Geräts genannt.
Die Slave-Adresse eines Geräts kann, mit Ausnahme der folgenden reservierten Adressen, frei vergeben werden.
- Die Adresse 0b0000000 ist als General Call Adresse reserviert.
- Alle Adressen vom Format 0b1111xxx sind für zukünftige Verwendung reserviert.
Bei vielen Geräten sind einige Bits der Slave-Adresse bereits fest vorgegeben und die restlichen Bits können durch die Beschaltung konfiguriert werden. Das zugehörige Datenblatt des jeweiligen Geräts sollte dabei Auskunft darüber geben, welcher Teil der Adresse fest vorgegeben, und welcher Teil konfigurierbar ist.
Master
[Bearbeiten]Bevor ein Datenaustausch über den TWI Bus stattfinden kann, muss zunächst ein Gerät die Kontrolle über den Bus übernehmen. Ein Gerät, das aktuell die Kontrolle über den Bus hat, wird Master genannt.
Der Datenaustausch auf dem TWI Bus findet immer zwischen einem Master und einem oder mehreren Slaves statt.
Bei der Kommunikation mit einem Slave kann der Master sowohl als Sender, als auch als Empfänger agieren. Bei einer Kommunikation mit mehreren Slaves können nur Daten vom Master zu den Slaves transportiert werden.
Datenpakete
[Bearbeiten]Der Datenaustausch auf dem TWI Bus findet in Einheiten von 9-bit statt. Die einzelnen Bits eines Datenpakets werden im Takt der SCL Leitung sequentiell auf die SDA Leitung gelegt. In den ersten 8 Bit legt der Sender die zu übertragenden Daten auf den Bus. Das letzte Bit wird vom Empfänger gesetzt. Die beiden möglichen Zustände dieses Bits werden auch als ACK und NACK bezeichnet.
Protokoll
[Bearbeiten]Start und Stop Condition
[Bearbeiten]Zu ein und demselben Zeitpunkt kann maximal ein Gerät auf dem TWI Bus Master sein. Ein TWI Bus auf dem gerade ein Gerät Master ist wird auch als busy bezeichnet.
Ist der TWI Bus nicht busy, so kann sich ein Gerät selbst zum Master machen, indem es ein spezielles Signal versendet. Dieses Signal wird auch START condition genannt. Sendet ein Gerät, das bereits Master ist, erneut das spezielle Start Signal, so wird dieses Signal auch RESTART condition genannt.
Um die Kontrolle über den TWI Bus wieder abzugeben, kann der Master ein spezielles Signal versenden. Dieses Signal wird auch STOP condition genannt.
Adressierung
[Bearbeiten]Um mitzuteilen mit welchem Gerät er kommunizieren möchte, und ob er als Sender oder Empfänger fungieren möchte, muss der Master nach einer START bzw. einer RESTART condition ein Adress-Byte über den Bus versenden.
Die hochwertigen 7-bit des Adress-Bytes geben die Slave-Adresse des Geräts an, mit dem kommuniziert werden soll. Das niederwertige Bit gibt an, ob der Master lesen (1) oder schreiben (0) möchte. Abhängig von diesem Bit wird das Adress-Byte auch als SLA+W bzw. SLA+R Byte bezeichnet.
Befindet sich ein Gerät mit der gewünschten Adresse am TWI Bus und ist es aktuell in der Lage mit dem Master zu kommunizieren, so setzt es das letzte Bit des Adress-Datenpakets auf den Wert ACK. Ist kein Gerät mit der gewünschten Adresse vorhanden, oder ist das adressierte Gerät aktuell nicht in der Lage mit dem Master zu kommunizieren, so bleibt das letzte Bit auf dem Wert NACK.
Ein Adress-Byte kann nur direkt nach dem Senden einer START condition oder einer RESTART condition versendet werden.
Datenaustausch
[Bearbeiten]Nachdem die Kommunikationspartner und ihre Rollen als Sender und Empfänger festgelegt sind, kann mit der Übertragung der Daten begonnen werden. Der Sender verschickt die Daten ein Byte nach dem anderen. Der Empfänger teilt im letzten im letzten Bit der Datenpakete durch Setzen von ACK mit, dass er am Empfang weiterer Daten interessiert ist. Ist er nicht am Empfang weiterer Daten interessiert, so setzt er das letzte Bit auf NACK.
AVR Microcontroller
[Bearbeiten]Der AVR Microcontroller kann am TWI Bus sowohl als Master als auch als Slave betrieben werden.
Die Lage der vorgesehenen Pins kann im Datenblatt nachgesehen werden. Für einen AtMega328p kann die Zuordnung der Pins der folgenden Tabelle entnommen werden.
TWI Pin | alias |
---|---|
SDA | PC4 |
SCL | PC5 |
Damit sie für die Ansteuerung des TWI Bus verwendet werden können, müssen beide Pins als Input Pins konfiguriert werden und die internem Pull-up Widerstände beider Pins aktiviert werden.
Initialisierung
[Bearbeiten]Damit er am TWI Bus arbeiten kann muss das Power Reduction Bit PRTWI0 im PRR Register auf dem Wert 0 stehen. Nach einem Wechsel des PRTWI0 Bits von 1 auf 0 sollte die TWI Schnittstelle des Arduino laut Handbuch reinitialisiert werden. [2]
Master
[Bearbeiten]Wenn der Controller als Master arbeitet, gibt er die Taktfrequenz der SCL Leitung vor. Die Frequenz des SCL Takts kann als Bruchteil der CPU Taktfrequenz eingestellt werden.
Der Bruchteil kann mit einem 8-bit Wert im TWBRR Register und einem 2-bit Wert mit den Bits TWPS1 und TWPS0 im Register TWSR Register angegeben werden. Die Formel zur Berechnung kann im Handbuch nachgesehen werden. [3]
Achtung! Beim Setzen des Prescalers (Bits TWPS1, TWPS1 im Register TWSR) ist darauf zu achten die restlichen Bits im TWSR Register unverändert zu lassen! In ihnen ist der Status codiert.
Wird er versehentlich verändert bringt dies die TWI Hardware durcheinander.Slave
[Bearbeiten]Wenn der AVR Controller als Slave betrieben werden soll, so muss ihm eine Geräteaddresse zugeteilt werden. Die Bits TWAR6 ... TWAR0 im Register TWAR geben die Slave-Adresse an.
Wenn der Controller auch auf die General Call Adresse (0x00) reagieren soll, dann muss das TWGCE Bit im Register TWAR auf 1 gesetzt werden. Wenn er nicht auf sie reagieren soll, muss sie auf 0 gesetzt werden.
Arbeitsweise
[Bearbeiten]Die TWI Funktionseinheit modeliert die Kommunikation über den TWI Bus mit einem Zustandsdiagramm.
Zustände
[Bearbeiten]Jeder Knoten repräsentiert einen Zustand, in dem sich TWI Funktionseinheit und TWI Bus befinden. Der Zustand, in dem sich die TWI Funktionseinheit befindet, kann im TWSR (TWI Status Register) Register ausgelesen werden.
Achtung! Beim Auslesen des TWSR (Two Wire Status Register) Registers nicht vergessen die Prescaler-Bits auszumaskieren.
Die Header Datei <util/twi.h> der AVR Libc enthält ein Makro TW_STATUS, das diese Aufgabe übernimmt. Es ist wie folgt definiert.
#define TW_STATUS_MASK (_BV(TWS7)|_BV(TWS6)|_BV(TWS5)|_BV(TWS4)|_BV(TWS3))
#define TW_STATUS (TWSR & TW_STATUS_MASK)
Übergänge
[Bearbeiten]Übergänge können mit dem TWCR (TWI Control Register) ausgelöst werden. Das Flag TWINT (TWI Interrupt Flag) im TWCR (TWI Control Register) Register wird nach jedem Ereignis auf dem TWI Bus auf den Wert 1 gesetzt.
Ein Blick auf das vollständige Diagramm kann unübersichtlich wirken. Bevor wir einen Blick auf das vollständige Diagramm werfen, werden wir uns daher zunächst eine Reihe einfacher Fälle ansehen.
Single Master System
[Bearbeiten]Der häufigste Fall.
Master
[Bearbeiten]Der häufigste Fall. Der Microcontroller wird für die Ansteuerung eines oder mehrerer Slaves verwendet. Dabei kann es sich z.B. um ein LCD Display oder einen EEPROM Speicher handeln.
Slave
[Bearbeiten]In einem Single Master System gibt es drei Einstiegspunkte
- read
- write (Slave Adresse)
- write (gcall Adresse)
Multi Master System
[Bearbeiten]TODO:
Interruptbetrieb
[Bearbeiten]Die TWI Funktionseinheit kann sowohl synchron mit dem Programmfluss, als auch mit Interrupt betrieben werden. Um den Interrupt Betrieb zu aktivieren muss das Bit TWIE (TWI Interrupt Enable) im TWCR (TWI Control Register) Register auf den Wert 1 gesetzt werden.
Synchroner Master
[Bearbeiten]Die TWI Funktionseinheit kann sowohl synchron mit dem Programmfluss, als auch mit Interrupt betrieben werden. Wenn sie synchron mit dem Programmfluss verwendet wird, muss das Bit TWINT im TWCR Register regelmäßig überprüft/gepollt werden, um herauszufinden, ob eine Aktion ausgeführt werden muss. Für einen Betrieb als Slave scheint dieser Ansatz nicht besonders praktikabel, da zu bearbeitende Ereignisse zu unvorhersehbaren Zeitpunkten eintreffen können. Ein wenig anders liegt die Sache bei einem Betrieb als Master. Die Zeitpunkte, zu denen der Status des TWINT Bits abfragt werden muss, sind hier durch den Programmfluss vorgegeben.
Initialisierung
[Bearbeiten]Operationen
[Bearbeiten]void twi_stop() {
TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN);
}
uint8_t twi_start() {
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);
loop_until_bit_is_set(TWCR, TWINT);
return TW_STATUS;
}
uint8_t twi_write(uint8_t data) {
TWDR = data;
TWCR = _BV(TWINT) | _BV(TWEN);
loop_until_bit_is_set(TWCR, TWINT);
return TW_STATUS;
}
uint8_t twi_sla_w(uint8_t slave_address) {
uint8_t byte = (uint8_t) (slave_address << 1) | TW_WRITE;
return twi_write(byte);
}
uint8_t twi_sla_r(uint8_t slave_address) {
uint8_t byte = (uint8_t) (slave_address << 1) | TW_READ;
return twi_write(byte);
}
uint8_t twi_read_ack(uint8_t *data) {
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN);
loop_until_bit_is_set(TWCR, TWINT);
*data = TWDR;
return TW_STATUS;
}
uint8_t twi_read_nack(uint8_t *data) {
TWCR = _BV(TWINT) | _BV(TWEN);
loop_until_bit_is_set(TWCR, TWINT);
*data = TWDR;
return TW_STATUS;
}
Rückschau und Ausblick
[Bearbeiten]Glückwunsch! Du bist nun mit allen Grundlagen vertraut, die Du benötigst, um an den TWI Bus angeschlossene Slaves mit dem Microcontroller steuern.
Im nächsten Kapitel wird es ausschließlich um die elektrischen Eigenschaften des TWI Bus und die Implementierung einer Software Lösung gehen, mit der der Microcontroller auch ohne integrierte TWI Funktionseinheit am TWI Bus betrieben werden kann.
Wenn Du nicht so sehr an den technischen Details interessiert bist und über einen Microcontroller mit integrierter TWI Funktionseinheit verfügst, kannst Du das folgende Kapitel überspringen.
Fußnoten
[Bearbeiten]- ↑ Das Datenblatt [M328p] nennt in 26.2 Two-Wire Serial Interface Bus Definition, S.260 die Zahl 128. Faktisch dürften es allerdings nur 120 = 128 - 1 (General Call) - 7 (reserviert für zukünftige Verwendung) Geräte sein.
- ↑ (siehe [M328p]: 14.12.3. Power Reduction Register, S. 71)
- ↑ (siehe [M328p]: 26.5.2. Bit Rate Generator Unit, S. 266)