GPIO Tutorial-Reihe - Part 4: Schieberegister

Mit ** gekennzeichnete Links auf dieser Seite sind Affiliatelinks.

GPIO Tutorial-Reihe - Part 4: Schieberegister
GPIO Tutorial-Reihe - Part 4: Schieberegister
  • Matthias Kleine
  • 27.09.2017
  • Hardware
  • Grundlagen

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

Hausbau-Kurs

Schaltplan

GPIO Schieberegister

»GPIO Schieberegister«

Komponenten

SUNFOUNDER Ultimate Starter Kit für Raspberry Pi 4 B 3 B+ 400, Deutscher Tutorial, Python C Code, 216 Artikel, Elektronische Kit für Raspberry Pi zum Lernen Elektronik und Programmierung **

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.

Du willst mehr?

Smart-Home-Trainings von A-Z

Steig noch tiefer in die Themen ein und meistere Deine Projekte! Über 13.000 Teilnehmer konnten sich schon von der Qualität der Online-Kurse überzeugen.

ioBroker-Master-Kurs

ioBroker-Master-Kurs

Mehr Infos
Hausbau-Kurs

Hausbau mit KNX

Mehr Infos
Lox-Kurs

Lox-Kurs

Mehr Infos
Node-RED-Master-Kurs

Node-RED-Master-Kurs

Mehr Infos