Arduino Mikrocontroller Tutorials - Schnittstellen

shiftIn() / shiftOut()

Die beiden Arduino Funktionen shiftOut() und shiftIn() funktionieren ähnlich wie die hardwareseitige SPI Schnittstelle. Nur eben als Softwarelösung. Die beiden Funktionen sind wesentlich langsamer als SPI, können aber im Gegensatz dazu an allen I/O Ports eingesetzt werden.

shiftOut()

Oszibild shiftOUT()

Der Funktion shiftOut(Data, Clock, Bitorder, Byte) werden folgende Parameter mitgegeben:

Für Empfänger die die Daten hardwareseitig mit einem Schieberegister empfangen wird neben der Daten und CLK Leitung noch eine CS (oder auch SS oder Latch) Leitung zur Übertragung benötigt. Über diese Leitung wird das Eingangsregister des Datenempfängers geschalten. Während der Übertragung wird diese Leitung auf LOW gelegt. Sobald CS am Ende wieder auf HIGH geht werde die Daten im Eingangsregister vom Empfänger übernommen. Die genaue Funktion dieser ChipSelect/Latch Leitung wird Kapitel "Schieberegister" im Detail beschrieben.

Beispiel

byte sendeDaten = B10100110; shiftOut(Daten_Pin, CLK_Pin, MSBFIRST, sendeDaten); digitalWrite(CS, HIGH); digitalWrite(CS, LOW);

Source Code von shiftOut()

Hier ist zur Information der in der Arduino IDE hinterlegte Source Code von shiftOut() abgebildet. Unit8_t wird hier als Synonym für eine byte Variable verwendet.

Abhängig von welcher Seite die Bits übertragen werden sollen (Bitorder LSBFIRST oder MSBFIRST) wird jedes Bit überprüft ob dieses eine logische '0' oder '1' enthällt. Dieses einzelne Bit wird dann mit digitalWrite() auf den Daten Ausgang gelegt. Am Ende jedes Bits wird dann mit einem kurzen Clockpuls dem Empfängerregister signalisiert, dass der Wert auf der Datenleitung übernommen werden soll.

void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val){ uint8_t i; for (i = 0; i < 8; i++) { if (bitOrder == LSBFIRST) digitalWrite(dataPin, !!(val & (1 << i))); else digitalWrite(dataPin, !!(val & (1 << (7 - i)))); digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW); } }

Mit 1<<i wird eine "walking 1" erzeugt. Bei i=0 ist dies B00000001, bei i=1 B00000010 und bei i=7 schließlich B10000000. Mit dem bitweisen UND (&) wird das Übertragungsbyte jeweils verglichen. Ist die i’te Stelle des Bytes ebenfalls 1 wird als Ergebnis 1 zurückgegeben. Ansonsten 0. (Für weitere Infos siehe Kapitel Bitoperationen).

Das Ergebnis von (val & (1 << i)) ist ein Bytewert der 0 ist (Bsp B0000000) oder an irgendeiner Stelle i eine 1 hat (Bsp B0010000). Für die digitalWrite() Funktion wird aber eine boolsche '1' oder '0' bzw. HIGH/LOW benötigt und keine Zahl. Mit der logischen Negierung ! wird das Byte zu einem boolschen Wert umgewandelt. Da aus einer Zahl (Bsp B0010000) durch die Negierung jetzt aber false geworden ist und aus einer 0 ein boolsches true wird durch ein zweites ! nochmal zurück negiert.

shiftIn()

Die Funktion shiftIn(Data, Clock, Bitorder) gibt das empfangene Byte als Wert zurück. Folgende Parameter müssen angegeben werden:

Beispiel

digitalWrite(CS, LOW); digitalWrite(CS, HIGH); byte empfangeneDaten = shiftIn(Daten_Pin, CLK_Pin, LSBFIRST); Serial.println(empfangeneDaten); delay(500);

Source Code von shiftOut()

unit8_t ist wieder ein Synonym für byte. Sobald die Clockleitung auf HIGH ist wird der anliegende Pegel von der Datenleitung übernommen und an die i’te Stelle des Empfangsbytes geschrieben. Anschließend wird die Clockleitung wieder auf LOW gelegt. Der Sender kann jetzt den Pegel des nächsten Bits auf die Datenleitung legen. Sobald alle 8 Bits empfangen sind, wird mit return value das zusammengestellte Empfangsbyte ausgegeben.

uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) { uint8_t value = 0; uint8_t i; for (i = 0; i < 8; ++i) { digitalWrite(clockPin, HIGH); if (bitOrder == LSBFIRST) value |= digitalRead(dataPin) << i; else value |= digitalRead(dataPin) << (7 - i); digitalWrite(clockPin, LOW); } return value; }