GPIO Tutorial-Reihe - Part 4: Schieberegister

Mit ** gekennzeichnete Links auf dieser Seite sind Affiliatelinks.

Einige Leser haben mir schon gutes Feedback zu der Reihe gewünscht und mich gefragt, wie man denn die Anzahl der GPIO-Pins erhöhen könnte. Eine Möglichkeit dafür sind sogenannte Schieberegister zu nutzen. Wie diese genau funktionieren, und was man damit anstellen kann, wird alles in diesem Video gezeigt.

Was wird benötigt?

  • Eine FHEM-Installation
  • Ein Raspberry Pi (1, 2 oder 3)
  • Schieberegister vom Typ 74HC595
  • Ein paar LEDs oder wie hier im Beispiel eine 7-Segment-Anzeige

Video

Arduino-Kurs

Schaltplan

GPIO Schieberegister

Komponenten

Quellcode

Der komplett Quelltext aus diesem Video sieht wie folgt aus. Im ersten Beispiel werden hier alle Zahlen und Buchstaben von 0-9 und von a-f durchlaufen.

vi segmentcount.c 
gcc segmentcount.c -o segmentcount -lwiringPi
sudo ./segmentcount

In die Datei segmentcount.c (der Name ist dabei egal) kommt der folgende Inhalt:

#include <wiringPi.h>
#include <stdio.h>

#define SDI   0   // serial data input
#define RCLK  1   // memory clock input(STCP)
#define SRCLK 2   // shift register clock input(SHCP)

#define NUMBER_0 0x3f
#define NUMBER_1 0x06
#define NUMBER_2 0x5b
#define NUMBER_3 0x4f
#define NUMBER_4 0x66
#define NUMBER_5 0x6d
#define NUMBER_6 0x7d
#define NUMBER_7 0x07
#define NUMBER_8 0x7f
#define NUMBER_9 0x6f

#define LETTER_A 0x77
#define LETTER_B 0x7c
#define LETTER_C 0x39
#define LETTER_D 0x5e
#define LETTER_E 0x79
#define LETTER_F 0x71

#define DOT 0x80

unsigned char SegCode[17] = {
    NUMBER_0,
    NUMBER_1,
    NUMBER_2,
    NUMBER_3,
    NUMBER_4,
    NUMBER_5,
    NUMBER_6,
    NUMBER_7,
    NUMBER_8,
    NUMBER_9,
    LETTER_A,
    LETTER_B,
    LETTER_C,
    LETTER_D,
    LETTER_E,
    LETTER_F,
    DOT
};

void init(void)
{
    pinMode(SDI, OUTPUT);
    pinMode(RCLK, OUTPUT);
    pinMode(SRCLK, OUTPUT);

    digitalWrite(SDI, 0);
    digitalWrite(RCLK, 0);
    digitalWrite(SRCLK, 0);
}

void hc595_shift(unsigned char dat)
{
    int i;

    for (i = 0; i < 8; i++) {
        digitalWrite(SDI, 0x80 & (dat << i));
        digitalWrite(SRCLK, 1);
        delay(1);
        digitalWrite(SRCLK, 0);
    }

    digitalWrite(RCLK, 1);
    delay(1);
    digitalWrite(RCLK, 0);
}

int main(void)
{
    int i;

    if (wiringPiSetup() == -1) {
        printf("setup wiringPi failed !");
        return 1; 
    }

    init();

    while (1) {
        for (i = 0; i < 17; i++) {
            hc595_shift(SegCode[i]);
            delay(500);
        }
    }

    return 0;
}

Als nächstes wird im Video noch ein Countdown gezeigt, welcher von 99 bis 0 runter zählt. Dieser wurde mit dem folgenden C-Programm realisiert.

#include <wiringPi.h>
#include <stdio.h>
#include <math.h>

#define SDI   0   //serial data input
#define RCLK  1   //memory clock input(STCP)
#define SRCLK 2   //shift register clock input(SHCP)

#define NUMBER_0 0x3f
#define NUMBER_1 0x06
#define NUMBER_2 0x5b
#define NUMBER_3 0x4f
#define NUMBER_4 0x66
#define NUMBER_5 0x6d
#define NUMBER_6 0x7d
#define NUMBER_7 0x07
#define NUMBER_8 0x7f
#define NUMBER_9 0x6f

#define LETTER_A 0x77
#define LETTER_B 0x7c
#define LETTER_C 0x39
#define LETTER_D 0x5e
#define LETTER_E 0x79
#define LETTER_F 0x71

#define DOT 0x80

unsigned char SegCode[17] = {
    NUMBER_0,
    NUMBER_1,
    NUMBER_2,
    NUMBER_3,
    NUMBER_4,
    NUMBER_5,
    NUMBER_6,
    NUMBER_7,
    NUMBER_8,
    NUMBER_9
};

void init(void)
{
    pinMode(SDI, OUTPUT);
    pinMode(RCLK, OUTPUT);
    pinMode(SRCLK, OUTPUT);

    digitalWrite(SDI, 0);
    digitalWrite(RCLK, 0);
    digitalWrite(SRCLK, 0);
}

void hc595_shift(unsigned char dat)
{
    int i;

    for (i = 0; i < 8; i++) {
        digitalWrite(SDI, 0x80 & (dat << i));
        digitalWrite(SRCLK, 1);
        delay(1);
        digitalWrite(SRCLK, 0);
    }
}

void hc595_shift_2(unsigned char datl, unsigned char datr)
{
    hc595_shift(datr);
    hc595_shift(datl);

    digitalWrite(RCLK, 1);
    delay(1);
    digitalWrite(RCLK, 0);
}

int main(void)
{
    int i;

    if (wiringPiSetup() == -1) {
        printf("setup wiringPi failed !");
        return 1; 
    }

    init();

    while(1) {
        for (i = 99; i >= 0; i--) {
            int right = i % 10;
            int left = i / 10;

            hc595_shift_2(SegCode[left], SegCode[right]);
            delay(1000);
        }
    }

    return 0;
}

Jetzt könnte man das Ganze noch so erweitern, dass z.B. ein Parameter genutzt wird um einzelne Zustände zu übergeben. Das schwerste ist eigentlich zu realisieren, dass man sich die Zustände der einzelnen Ausgänge merkt, da man immer das komplette Schieberegister übergeben muss um einzelne Werte zu ändern.


Newsletter

Trage Dich jetzt in den Newsletter ein und genieße dadurch viele Vorteile:

  • 5€-Gutschein als Dankeschön
  • Zugang zu exklusiven Inhalten
  • Angebote für Produkte

* Durch Angabe meiner E-Mail-Adresse erkläre ich mich damit einverstanden, dass mir regelmäßig Informationen und Produktempfehlungen aus dem Fachgebiet Smart Home zugesendet werden. Mit dem Eintrag akzeptieren Sie unsere Datenschutzbestimmungen. Meine Einwilligung kann ich jederzeit widerrufen.

Auf YouTube und hier im Blog gibt es bereits unzählige kostenlose Videos, Informationen und Tutorials. Wenn Dir das noch nicht reicht, ist ein Training genau das richtige für Dich! Die folgenden Trainings haben den Vorteil, dass immer von Anfang an gestartet wird und Du ohne Vorwissen teilnehmen kannst.