SPI
Man glaubt es kaum, aber SPI haben wir schon verwendet. Die Verbindung zur SD Karte war ein SPI Hardware Protokoll, weswegen wir die Pin's nicht frei definieren konnten. Diese Bibliothek stellt nun das Hardwareprotokoll direkt zur Verfügung.
Aber was ist nun SPI. SPI ist ein serielles Protokoll speziell mit Microcontroller. Es gibt immer einen Master und n Slaves. (Also einen der das ganze steuert und viele die nur konsumieren.) DIese Bibliothek implementiert den Arduino als Master. Um das ganze zu bewerkstelligen gibt es 3 Leitungen.
- MOSI, Master Out Slave In, das ist die Leitung, wo die Daten vom Master zum Slave laufen
- MISO, Master In Slave Out, das ist die Rückleitung, hier laufen die Daten vom Slave zum Master
- SCLK, System Clock, das ist die Taktleitung. Der Takt wird vom Master vorgegeben.
- SS, Slave Select, das ist eine Leitung die vom Master zum Slave geht. Jeder Slave hat da seine eigene Leitung. Nur wenn diese Null ist, reagiert der Slave auf die Daten. Will man also mehrere Slaves an den Bus anschliessen, können sich alle beteiligten die Leitungen MOSI, MISO, SCLK teilen. Allerdings muss jeder Slave eine eigene SS Leitung haben. Kleiner Tipp, macht die Leitungen nicht zu lang, sonst könnte es Probleme mit Einstreuungen geben. Das SPI Protokoll ist nicht gerade Fehlertolerant.
Wenn man nun ein SPI Gerät anschliessen möchte, muss man folgende Dinge wissen:
- In welcher Reihenfolge erwartet der Slave die Daten. SPI ist ja ein serielles Protokoll, d.h. die DAten werden Bitweise durch die Leitung geschoben. Da ist es wichtig, zu wissen, ob zuerst das bit 0 (LSB) kommt oder das bit 7 (MSB). In der Bibliothek kann man das einstellen mit SPI.setBitOrder().
- Auf welchen Taktimpuls reagiert der Slave, auf den positiven oder den negativen. Und an welcher Flanke werden die Daten abgegriffen. Das alles wird mit SPI.setDataMode() eingestellt.
- Und welche Geschwindigkeit kann der Slave verarbeiten. Das wird mit der SPI.setClockDivider() Funktion eingestellt.
Leider ist das SI Protokoll nicht gerade stark Standartisiert, so macht jeder Hersteller alles ein klein wenig anders. Deshalb kommt man um das Datenblatt lesen nicht herum.
Mehr zu lesen gibt's hier: Wikipedia Eintrag zum Thema SPI.
Hier noch die Tabelle für die Taktimpuls und -phase.
Modus | Taktpolarität | Taktphase |
---|---|---|
0 | 0 (reagiert auf High) | 0 (fallender Flanke) |
1 | 0 | 1 (steigender Flanke) |
2 | 1 (reagier auf Low) | 0 |
3 | 1 | 1 |
Auf dem Arduino Duemilanove oder auch anderen Arduino Board mit dem ATMega168/328 belegt der SPI Bus folgende Pins. Pin 11 MOSI, Pin12 MISO, Pin 13 SCLK, und Pin 10 ist überlicherweise SS. Selbst wenn man SS nicht benutzt (Weil man z.B. nur einen Slave am SPI hat), muss der SS Pin angegeben und als Ausgang definiert sein. Sonst funktioniert die Bibliothek nicht. MAn kann den SS Pin aber auch umlegen. z.B. die Arduino Ethernet Shield benutzt den Pin 4 als SS für die eingebaute SD Karten und Pin 10 für den Ethernetcontroller selber.
So und nun zu den Funktionen.
SPI.begin()
Initialisiert den SPI bus, setzt SCK, MOSI, und SS als Ausgang, setzt SCK und MOSI auf 0 and SSauf 1
SPI.end()
Beendet die Verbindung. Dei Pins bleiben unverändert.
SPI.setBitOrder(Reihenfolge)
Setzt die Bitreihenfolge, mögliche Werte sind: LSBFIRST (niederwertigste Bit zuerst) oder MSBFIRST.
SPI.setClockDivider(Teiler)
Setzt den Taktteiler. Der Takt wird direkt vom Systemtakt abgeleitet und nur durch einen Vorteiler geteilt. Mögliche Werte sind: 2, 4, 8, 16, 32, 64, or 128. Z.B: ist der Standart SPI_CLOCK_DIV4, was bedeutet, daß ein Vorteiler von 4 eingeschaltet ist. Bei einem Systemtakt von 8MHz sind das also 2MHZ Takt für das SPI Interface. mögliche Werte: SPI_CLOCK_DIV2, SPI_CLOCK_DIV4, SPI_CLOCK_DIV8,SPI_CLOCK_DIV16, SPI_CLOCK_DIV32, SPI_CLOCK_DIV64, SPI_CLOCK_DIV128
SPI.setDataMode(Modus)
Setzt den Modus wann die Daten in bezug auf den Takt übernommen werden. Mögliche Werte sind: SPI_MODE0, SPI_MODE1, SPI_MODE2, oder SPI_MODE. Tabelle dazu weiter oben.
byte slaveDaten = SPI.transfer(Daten)
Daten ist das zu versendende Datenbyte. Gleichzeitig wird auch ein Byte vom Slave gelesen.