Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

BitShifting ist eine Methode, bei welcher einzelne Bits nacheinander über einen Pin des Arduino “geshiftet” – d.h. herausgeschrieben – werden. Diese Funktion kann genutzt werden um z.B. mehrere LEDs mit nur wenigen Pins anzusteuern. Dies kann Sinn machen, wenn man z.B. eine Segmentanzeige mit vielen Stellen steuern möchte.

Hintergrund

Um die Funktionsweise des BitShifting zu verstehen hilft es, sich die grundlegenden Operationen des Microkontrollers vorzustellen. Ein Microkontroller – wie jede andere CPU auch – arbeitet nur auf der Basis von 0 (AUS) und 1 (EIN). Diese werden so verarbeitet, dass logische Systeme damit konstruiert werden können. Die Basis dafür bilden die sog. bitweisen Operanden. Ein Byte besteht grundsätzlich aus acht Bits. Man kann sich den Zusammenhang zwischen Bits und Bytes also folgendermassen vorstellen…

BILD

D.h. alle Werte der Bits in einem Byte zusammengenommen ergeben den Wert des Bytes. Dabei gilt folgende Logik …Shifting out is a method in which individual bits are "shifted" - i.e. written out - one after the other via a pin of the Arduino. This function can be used for example to control multiple LEDs with just a few pins.

Background

To understand how shifting out works, it helps to imagine the basic operations of the microcontroller. A microcontroller - like any other CPU - only works on the basis of 0 (OFF) and 1 (ON).  A byte consists of eight bits.

In one byte we can store up to 256 unique values (from 0 to 255).  

0000 0000 0

0000 0001 1

...

0000 0101 5
...
1111 1111 255 

Durch alle Kombinationen lassen sich so mit jedem Byte 256 Werte (von 0 bis 255) darstellen, je nachdem, welches Bit “aktiv” und welches “nicht aktiv” ist. Im folgenden Tutorial wird genau dies mit dem “Beispiel ShiftOut 01″ visualisiert.

Der Wert des Bytes lässt sich also entweder durch die Summe der Werte der Bits bestimmen oder man setzt direkt den Wert des Bytes, welches wiederum die Werte der Bits verändertThe value of the byte can either be determined by the sum of the values of the bits or each bit can be set directly. In C/C++ haben wir durch einige definierte Funktionen Zugriff auf diese Werte – durch die sog. bitweisen Operanden. Möchte man also z.B. das dritte Bit in einem Byte verändern gibt es folgende drei Möglichkeiten…we have access to these values through some defined functions - through the so-called bitwise operations. For example, if you want to change the third bit in a byte, there are three options...

byte test = B00100000; // Direkte Zuweisung des Bit WertesWe can writes bits directly with this notation
byte test = 40// Zuweisung über den Wert des Bytes We can writes the decimal sum of all bites like this 
byte test = bitWrite(test, 3, HIGH); // Zuweisung des Wertes über die Funktion bitWrite() 

Wenn wir uns nun vorstellen, dass jedes Bit eine LED darstellt, welche je nach Wert des Bits aus EIN od. AUS gesetzt wird, dann können wir mit Hilfe eines Bytes acht unterschiedliche LEDs ansteuern. Es geht also lediglich darum, wie wir ein Byte versenden und dann wieder so decodieren können um damit eine LED zu schalten. Dafür nutzen wir ein ShiftRegister des Types 75HC595. Dieses erlaubt es uns über einen Daten PIN (DATA_PIN) das gesamte Byte zu senden und je nach dessen Wert bis zu acht Ausgänge zu schalten.

Image Removed

Die Funktion ShitOutwe can set individual bits like this

If we now imagine that each bit represents an LED, which is set ON or OFF depending on the value of the bit, then we can control eight different LEDs with the help of one byte. So it's just a matter of how we can send a byte and then decode it in such a way that we can use it to switch an LED. For this we use a ShiftRegister, specifically the 75HC595. This allows us to send the entire byte via a data PIN (DATA_PIN) and to switch up to eight outputs depending on its value.

Image Added



The function shiftOut(DATA_PIN, CLOCK_PIN, bitOrder, Wert) übernimmt dabei das Timing und das Herausschreiben des kompletten Bytes. DATA_PIN ist dabei der PIN, über welchen die Daten versandt werden. CLOCK_PIN ist für das Timing. bitOrder beschreibt ob wir das Byte von Links nach Rechts (MSBFIRST – most significant bit first) oder von Rechts nach Links (LSBFIRST – value) takes over the timing and the writing out of the complete byte. DATA_PIN is the PIN via which the data is sent. CLOCK_PIN is for timing. bitOrder describes whether we want to read the byte from left to right (MSBFIRST - most significant bit first) or from right to left (LSBFIRST - last significant bit first) lesen möchtenWert kennt dann nur noch zwei Zustände HIGH od. LOW.

BILD

Beispiel

Ein gutes Tutorial zur Verwendung eines Shift Registers ist hier dokumentiert. Folgende Komponenten werden für das Tutorial benötigt

Example

A good tutorial on using a shift register is documented here. The following components are required for the tutorial:

1x Arduino
1x Shift Register 74HC595 (DatenblattData-sheet)
1x Display Kingsbright (DatenblattData-sheet)
2x Breadboard Mini

Das Display besteht eigentlich aus 8 einzelnen LEDs, welche in der uns vertrauten Form angeordnet sind. Auf der Rückseite des Diplays befinden sich die entsprechenden Anschlüsse. Im Datenblatt des Diplays finden wir die Information, wie diese Anschlüsse belegt werden müssen.

Image Removed

Um das Shift Register ansprechen zu können, müssen wir uns zunächst das Timing des Registers ansehen. Hierzu gibt es im Datenblatt der 74HC595 ein sog. Timing Diagramm.

Image Removed

Mit Hilfe dieses Diagramms lässt sich erkennen, dass wir zunächst den LATCH_PIN auf LOW setzen müssen. Danach können die Daten an das Register geshiftet werden. Zum Abschluss wird der LATCH_PIN wieder auf HIGH gesetzt um die Ausgänge des Registers zu setzen und die LEDs zum leuchten zu bringenBreadboards

The display actually consists of 8 individual LEDs, which are arranged in the form a numeric segment display. The corresponding connections are located on the back of the display. In the data sheet of the display we find the information how these connections have to be assigned.

Image Added

In order to address the shift register, we first need to look at the timing of the register. There is a so-called timing diagram in the data sheet for the 74HC595.

Image Added

Using this diagram, it can be seen that we first need to set the LATCH_PIN to LOW. Then the data can be shifted to the register. Finally, the LATCH_PIN is set HIGH again to set the outputs of the register and to light up the LEDs.

Code Block
languagejava
titleBeispiel ShiftOut
collapsetrue
#define LATCH_PIN 8  //Pin zufor ST_CP vomon 74HC595
#define CLOCK_PIN 12 //Pin zufor SH_CP vomon 74HC595
#define DATA_PIN 11  //Pin zufor DS vomon 74HC595
 
void setup() 
{
  pinMode(LATCH_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(DATA_PIN, OUTPUT);
}
 
void loop() 
{
  for (int numberToDisplay = 0; numberToDisplay < 256; numberToDisplay++) 
  {
    digitalWrite(LATCH_PIN, LOW);  // LATCH_PIN aufto LOW = BeginnBegin
der Daten
      shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, numberToDisplay); // DatenData shiftenshifted
 
    digitalWrite(LATCH_PIN, HIGH);  // LATCH_PIN auf HIGH = LEDs leuchtenlight up
 
    delay(500);
  }
}

...

T

he first example shows how a byte is resolved at the bit level. The following example helps to really be able to address each individual pin of the register.


Code Block
languagejava
titleBeispiel BitWrite
collapsetrue
#define LATCH_PIN 8  //Pin zufor ST_CP vomon 74HC595
#define CLOCK_PIN 12 //Pin zufor SH_CP vomon 74HC595
#define DATA_PIN 11  //Pin zufor DS vomon 74HC595
 
void setup() 
{
  pinMode(LATCH_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(DATA_PIN, OUTPUT);
}
 
void loop() 
{
  for(int i=0; i<8; i++)
  {
    registerWrite(i, LOW); // Entsprechendeset specific LED anmachen
    delay(1000);
  }
}
 
void registerWrite(int _whichPin, int _whichState) 
{
 
  byte bitsToSend = 255; // DiesesThis Byte hathas acht8 Bits alsobits: 11111111
 
  digitalWrite(LATCH_PIN, LOW);
 
  bitWrite(bitsToSend, _whichPin, _whichState); //Here Hiera wirdspecific dasbit entsprechendeis Bit im Byte gesetzt (z.B.set (e.i 00100000)
 
  shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, bitsToSend);
 
  digitalWrite(LATCH_PIN, HIGH);
 
}

...