19.   SPI: Synchron-serielle Schnittstelle

19.1   Features

19.2   Überblick

Das serielle Peripherie-Interface (SPI) realisiert synchronen Datentransfer mit hoher Geschwindigkeit zwischen dem Controller und peripheren Bausteinen oder zwischen zwei AVR-Mikrocontrollern.

Auch die USART kann als SPI-Master verwendet werden, siehe USART im SPI-Modus. Das Bit PRSPI im Leistungsreduktions-Register muss gelöscht sein, damit das SPI-Modul funktioniert.

Bild 19-1: SPI-Blockdiagramm
Die Zusammenarbeit zwischen Master- und Slave-CPUs wird im Bild 19-2 dargestellt. Das System besteht aus zwei Schieberegistern und einem Master-Taktgenerator. Der SPI-Master initiiert einen Kommunikationszyklus, indem der den SS-Pin (Slave Select) des gewünschten Slaves auf Low-Pegel zieht. Der Master und der Slave bereiten die zu übertragenden Daten in ihren entsprechenden Schieberegistern vor und der Master generiert die erforderlichen Taktpulse auf der SCK-Leitung, damit die Daten ausgetauscht werden. Die Daten werden vom Master zum Slave immer über die „Master out Slave in“-Leitung (MOSI) geschoben und vom Slave zum Master über die „Master in Slave out“-Leitung (MISO). Nach jedem übertragenen Datenpaket synchronisiert der Master den Slave, indem die „Slave Select“-Leitung (SS) auf High-Potential legt.

Wenn der Baustein als Master konfiguriert ist, so hat das SPI keine automatische Kontrolle über die SS-Leitung. Sie muss durch die Software gesteuert werden um eine Kommunikation zu starten. Wenn dies geschehen ist, startet das Schreiben eines Bytes in das SPI-Datenregister SPDR den SPI-Taktgenerator und die Hardware schiebt die acht Bits in den Slave. Nachdem die acht Bits geschoben wurden, stoppt der SPI-Taktgenerator und das End of Transmission Flag (SPIF) wird gesetzt. Wenn das SPI-Interruptfreigabe-Bit (SPIE) im Register SPCR gesetzt ist, wird dann ein Interrupt ausgeführt. Der Master kann dann die Kommunikation fortsetzen, indem er ein weiteres Byte in das SPDR-Register schreibt. Oder er beendet die Kommunikation, indem er die „Slave Select“-Leitung (SS) auf High-Pegel zieht. Das zuletzt eingegangene Byte verbleibt im Puffer-Register und kann dort abgeholt werden.

Wenn der Baustein als Slave konfiguriert ist, schläft das SPI-Interface mit MISO im hochohmigen Zustand, solagne die SS-Leitung auf High gehalten wird. Die Software kann Daten in das SPI-Datenregister SPDR schreiben, allerdings werden die Daten nicht durch die am SCK-Pin eingehenden Takte ausgeschoben, bis der SS Pin auf Low gelegt wurde. Wenn ein Byte komplett geschoben wurde, wird das „End of Transmission“-Bit (SPIF) gesetzt. Wenn das SPI-Interruptfreigabebit (SPIE) im SPCR-Register gesetzt ist, wird ein Interrupt ausgeführt. Der Slave kann weitere Daten in SPDR schreiben, bevor die eingegangenen Daten gelesen wurden. Das zuletzt eingegangene Byte verbleibt im Puffer-Register und kann dort abgeholt werden.

Bild 19-2: Zusammenarbeit Master und Slave
Das System ist in Senderichtung einfach und in Empfangsrichtung zweifach gepuffert. Das bedeutet, dass ein zu übertragenes Byte erst dann in das SPI-Datenregister geschrieben werden kann, wenn eine laufende Übertragung komplett angeschlossen ist. Beim Empfangen von Daten muss ein empfangenes Byte gelesen werden, bevor die Übertragung des folgenden Bytes abgeschlossen ist. Andernfalls geht das zuerst empfangene Byte verloren.

Im Slave-Modus tastet die Kontrolllogik das ankommende Signal am SCK-Pin ab. Um ein korrektes Abtasten zu gewährleisten, sollte die Frequenz des SCK-Taktes nicht größer sein als fOSC/4.

Wenn das SPI freigegeben ist, stellt sich die Datenrichtung der Pins MOSI, MISO, SCK und SS wie folgt ein:

Tabelle 19-1: SPI Pinfunktionen
PinRichtung als SPI-MasterRichtung als SPI-Slave
MOSIbenutzerdefiniertEingang
MISOEingangbenutzerdefiniert
SCKbenutzerdefiniertEingang
SSbenutzerdefiniertEingang
Das nachfolgende Beispiel zeigt das Initialisieren des SPI als Master und eine einfache Datenübertragung. DDR_SPI aus dem Beispiel muss durch das aktuelle Datenrichtungsregister ersetzt werden, das die SPI-Pins kontrolliert. DD_MOSI, DD_MISO und DD_SCK muss ersetzt werden durch die aktuellen Datenrichtungsbits für diese Pins. Beispiel: Wenn MOSI an Pin PB5 liegt, dann DD_MOSI durch DDB5 ersetzen und DDR_SPI durch DDRB.
Kodebeispiel in Assembler
SPI_MasterInit:
	; Setze MOSI und SCK als Ausgang, alles andere als Eingang
	ldi	r17,(1<<DD_MOSI)|(1<<DD_SCK)
	out	DDR_SPI,r17
	; SPI-Master freigeben, Taktfrequenz = fck/16
	ldi	r17,(1<<SPE)|(1<<MSTR)|(1<<SPR0)
	out	SPCR,r17
	ret
SPI_MasterTransmit:	; Starte Daten-Senden (r16)
	out	SPDR,r16
Wait_Transmit:		; Warte bis Senden fertig
	in	r16, SPSR
	sbrs	r16, SPIF
	 rjmp	Wait_Transmit
	ret
Kodebeispiel in C
void SPI_MasterInit(void) {
/* Setze MOSI und SCK als Ausgang, alles andere als Eingang */
  DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK);
/* SPI-Master freigeben, Taktfrequenz = fck/16 */
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}
void SPI_MasterTransmit(char cData) {
/* Starte Daten-Senden */
  SPDR = cData;
/* Warte bis Senden fertig */
  while (!(SPSR & (1<<SPIF)));
}
Das folgende Beispiel zeigt das Initialisieren des SPI als Slave und einen einfachen Empfang von Daten.
Kodebeispiel in Assembler
SPI_SlaveInit:
	; Setze MISO als Ausgang, alles andere als Eingang
	ldi	r17,(1<<DD_MISO)
	out	DDR_SPI,r17
	ldi	r17,(1<<SPE)
	out	SPCR,r17	; SPI freigeben
	ret
SPI_SlaveReceive:	; Warte bis Empfang fertig
	in	r16, SPSR
	sbrs	r16, SPIF
	 rjmp	SPI_SlaveReceive
	in	r16,SPDR	; Lese empfangenes Datenbyte
	ret
Kodebeispiel in C
void SPI_SlaveInit(void) {
/* Setze MISO als Ausgang, alles andere als Eingang */
  DDR_SPI = (1<<DD_MISO);
/* SPI freigeben */
  SPCR = (1<<SPE);
}
char SPI_SlaveReceive(void) {
/* Warte bis Empfang fertig */
  while (!(SPSR & (1<<SPIF)));
/* Lese empfangenes Datenbyte */
  return SPDR;
}

19.3   SS-Pinfunktion

Nachfolgend wird die Funktion des SS-Pins in den verschiedenen Betriebsmodi beschrieben.

19.3.1   Slave-Modus

Wenn das SPI als Slave konfiguriert ist, ist das SS-Pin immer ein Eingang. Wenn SS auf Low gehalten wird, wird das SPI aktiviert und MISO wird zum Ausgang, wenn er durch den Anwender so konfiguriert wurde. Alle anderen Pins sind Eingänge. Wenn SS auf High gelegt wird, werden alle Pins Eingänge und das SPI wird deaktiviert, d.h. es kann keine Daten mehr empfangen. Man beachte, dass die SPI-Logik zurückgesetzt wird, wenn das SS-Pin auf High gelegt wird.

Das SS-Pin ist hilfreich für die Paket- oder Bytesynchronisation indem der Slave-Bitzähler synchron mit dem Master-Taktgenerator gehalten wird. Wenn das SS-Pin auf High liegt, setzt der SPI-Slave die Sende- und Empfangslogik zurück und verwirft alle teilweise empfangenen Daten.

19.3.2   Master-Modus

Wenn das SPI als Master konfiguriert ist (MSTR im SPCR gesetzt), kann der Anwender die Richtung des SS-Pins bestimmen.

Wenn SS als Ausgang konfiguriert ist, ist es ein allgemeines Ausgangspin, der die Funktion des SPI nicht beeinflusst. Gewöhnlich wird das Pin mit dem SS-Pin eines Slaves verbunden.

Wenn SS als Eingang konfiguriert ist, muss es auf High gehalten werden, um die Masterfunktion sicherzustellen. Wenn das SS-Pin durch die Peripherie auf Low gezogen wird, während SPI als Master mit SS-Pin als Eingang konfiguriert ist, wird das SPI-System dies so interpretieren, als sei sie von einem anderen Master als Slave angesprochen worden und damit beginnen, Daten an den vermeintlichen Master zu senden. Um Buskollisionen zu vermeiden, führt das SPI-System dann folgende Aktionen durch:

  1. Das MSTR-Bit im SPCR-Register wird gelöscht, folglich wird das SPI-System zum Slave. Damit werden die Pins MOSI und SCK zu Eingängen
  2. Das SPIF-Flag im SPSR wird gesetzt, und wenn der SPI-Interrupt freigegeben ist — und das I-Bit im SREG gesetzt ist — wird die Interruptroutine ausgeführt.
Wenn also eine interruptgesteuerte SPI-Übertragung im Mastermodus verwendet wird und die Möglichkeit besteht, dass das SS-Pin auf Low gezogen wird, so muss die Interruptroutine immer überprüfen, ob das MSTR-Bit noch gesetzt ist. Wenn das MSTR-Bit durch einen externen Slave Select gelöscht wurde, so muss es durch die Software wieder gesetzt werden, um den SPI Mastermodus zu reaktivieren.

19.4   Datenmodi

Es gibt vier verschiedene Kombinationen der SCK-Phase und -Polarität mit Bezug auf die seriellen Daten, die durch die CPHA- und CPOL-Bits festgelegt werden. Das Format des SPI-Datentransfers ist in den Timingdiagrammen dargestellt. Die Datenbits werden mit entgegengesetzten Flanken von SCK geschoben und übernommen, damit ausreichend Zeit für die Stabilisierung des Daten bleibt. Dies wird aus folgender Tabelle deutlich.
Tabelle 19-2: SPI-Datenmodi
DatenmodusBedingungErste FlankeZweite Flanke
0CPOL=0, CPHA=0abtasten (steigend)setzen (fallend)
1CPOL=0, CPAH=1setzen (steigend)abtasten (fallend)
2CPOL=1, CPHA=0abtasten (fallend)setzen (steigend)
3CPOL=1, CPHA=1setzen (fallend)abtasten (steigend)
Bild 19-3: SPI-Übertragung mit CPHA=0
Bild 19-4: SPI-Übertragung mit CPHA=1

19.5   Register-Beschreibung

19.5.1   SPCR — Kontrollregister

Bit76543210
(0x4C)SPIESPEDORDMSTRCPOLCPHASPR1SPR0SPCR
ZugriffR/WR/WR/WR/WR/WR/WR/WR/W
Startwert00000000
Wenn dieses Bit mit einer 1 beschrieben wird, ist der SPI-Interrupt freigegeben. Der Interrupt wird ausgeführt, wenn das I-Bit im SREG gesetzt ist und das SPIF Flag im SPSR Register gesetzt wird. Wenn dieses Bit mit einer 1 beschrieben wird, ist das SPI freigegeben. Es muss gesetzt werden um alle SPI-Operationen freizugeben. Wenn dieses Bit mit einer 1 beschrieben ist, werden die Daten mit dem LSB voran übertragen. Wenn dieses Bit gelöscht ist, werden die Daten mit dem MSB voran übertragen. Wenn dieses Bit mit einer 1 beschrieben ist, ist der Mastermodus ausgewählt, wenn es gelöscht ist, arbeitet die SPI im Slave-Modus. Wenn SS als Eingang konfiguriert ist und im Mastermodus auf Low gezogen wird, wird das MSTR-Bit gelöscht und SPIF im SPSR wird gesetzt. Der Anwender muss dann das MSTR-Bit wieder setzen um den Mastermodus zu reaktivieren. Wenn dieses Bit mit einer 1 beschrieben ist, ist SCK auf High, wenn er nicht benutzt wird. Ist das Bit gelöscht, so ist SCK auf Low, wenn er nicht benutzt wird. Siehe Timingdiagramme. Zusammengefasst ist die CPOL Funktion wie folgt:
Tabelle 19-3: CPOL-Funktion
CPOLVorderflankeRückflanke
0steigendfallend
1fallendsteigend
Dieses Bit legt fest, ob die Daten mit der Vorder- oder Rückflanke von SCK abgetastet werden. Siehe Timingdiagramme. Zusammengefasst ist die CPHA-Funktion wie folgt:
Tabelle 19-4: CPHA-Funktion
CPHAVorderflankeRückflanke
0abtastensetzen
1setzenabtasten
Dieses beiden Bits kontrollieren die Taktrate an SCK des Bausteins, wenn er im Mastermodus arbeitet. SPR1 und SPR0 haben keine Auswirkungen im Slavemodus. Die Beziehung zwischen SCK und der Oszillator Taktfrequenz fOSC ist nachfolgend dargestellt:
Tabelle 19-5: Beziehung zwischen SCK und Oszillatorfrequenz
SPI2XSPR1SPR0SCK-Frequenz
000fOSC/4
001fOSC/16
010fOSC/64
011fOSC/128
100fOSC/2
101fOSC/8
110fOSC/32
111fOSC/64
Das SPI2X-Bit befindet sich im SPI-Statusregister (SPSR)

19.5.2   SPSR — Statusregister

Bit76543210
(0x4D)SPIFWCOL-----SPI2XSPSR
ZugriffRRRRRRRR/W
Startwert00000000
Wenn eine serielle Übertragung komplett ist, wird dieses Bit gesetzt. Ein Interrupt wird ausgeführt, wenn SPIE in SPCR gesetzt ist und die Interrupts global freigegeben sind. Wenn SS im Mastermodus als Eingang definiert ist und auf Low gezogen wird, wird das Flag ebenfalls gesetzt. Das SPIF wird durch die Hardware automatisch gelöscht, wenn die dazugehörige Interruptroutine ausgeführt wird. Alternativ kann das Flag auch gelöscht werden, wenn zunächst das SPI-Statusregister mit gesetztem SPIF gelesen wird und danach ein Zugriff auf das SPI-Datenregister (SPDR) erfolgt. Das WCOL-Bit wird gesetzt, wenn in das SPI-Datenregister während einer laufenden Übertragung geschrieben wird. Das WCOL-Bit (und SPIF) werden gelöscht, wenn zunächst das SPI-Statusregister mit gesetztem WCOL gelesen wird und danach ein Zugriff auf das SPI-Datenregister (SPDR) erfolgt. Diese Bits sind reserviert und werden immer als 0 gelesen. Wenn dieses Bit gesetzt wird, verdoppelt sich die Taktfrequenz SCK, wenn SPI im Mastermodus betrieben wird. Das bedeutet, dass die maximale SCK-Frequenz halb so groß wie die Frequenz des CPU-Taktes sein kann. Wenn SPI im Slave-Modus arbeitet, ist das korrekte Arbeiten allerdings nur mit einer Frequenz kleiner fOSC/4 garantiert.

19.5.3   SPDR — Datenregister

Bit76543210
(0x4E)MSBLSBSPDR
ZugriffR/WR/WR/WR/WR/WR/WR/WR/W
StartwertXXXXXXXXundefiniert

Das SPI Data Register ist ein Schreib/Lese-Register, das für den Datenaustausch zwischen den Registern und dem SPI Schieberegister verwendet wird. Das Schreiben in das Register startet eine Datenübertragung. Beim Lesen wird auf einen Eingangspuffer des Schieberegisters zugegriffen.