GPIO Tutorial-Reihe - Part 4: Schieberegister
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
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.