7 Segment Anzeige am MCP23S17

Die Anzeige der Temperatur soll über zwei 7 Segment Anzeigen erfolgen. Um ein paar der kostbaren GPIO Ports des Pi zu sparen war die Verwendung eines Port Expander sinnvoll. Ich habe mich für den MCP23S17 entschieden, den man hier käuflich erwerben kann. Der MCP23S17 wird über den SPI Bus kontrolliert, das ist vorteilhaft, da die Anzeige über weitere 7 Segment Anzeigen erweitert werden kann die mit weiteren MCP23S17 am gleichen Bus gesteuert werden können. Der Port Expander verfügt über zwei Bänke mit jeweils 8 IO Ports, gerade genug um jeweils eine 7 Segment Anzeige zu steuern.

Das folgende Bild zeigt das Layout in der Fritzing Software.
7Segment mit MCP23S17

So sieht es dann letztendlich auf dem Experiementierbrett aus.
7Segment mit MCP23S17

Das Script wird mit zwei Parametern aufgerufen, z.B. perl ./7segments.pm 1 2. In diesem Fall erzeugt der Aufruf die Anzeige der Nummer 12. Jeglicher Parameter der nicht den Ziffern 0-9 entspricht schaltet das entsprechende 7 Segment Display aus.

#!/usr/bin/perl

use Device::BCM2835;
use strict;

# call set_debug(1) to do a non-destructive test on non-RPi hardware
# Device::BCM2835::set_debug(1);
Device::BCM2835::init()
|| die "Could not init library";

# Variables
my $test;
my $param1;
my $param2;

# read CLI params
($param1, $param2) = @ARGV;

if ($param1 !~ /[\d]/ || $param1 > 10) {
 $param1 = 10;
}

if ($param2 !~ /[\d]/ || $param2 > 10) {
 $param2 = 10;
}

# MCP23S17 Values
my $SPI_SLAVE_ADDR = 0x40;
my $SPI_IOCTRL     = 0x0A;
my $SPI_IODIRA     = 0x00;
my $SPI_IODIRB     = 0x01;
my $SPI_GPIOA      = 0x12;
my $SPI_GPIOB      = 0x13;

# MCP23S17-PINs
my $SCLK = 11;  # PIN11 = Serial-Clock
my $MOSI = 10;  # PIN10 = Master-Out-Slave-In
my $MISO = 9;   # PIN9  = Master-In-Slave-Out
my $CS   = 24;  # PIN24 = Chip-Select

# Digit Values
my @output10 = ( 0b10000001, 0b11100111, 0b10010010, 
                 0b11000010, 0b11100100, 0b11001000, 
                 0b10001000, 0b11100011, 0b10000000, 
                 0b11000000, 0b11111111 );
my @output1  = ( 0b10000001, 0b11111001, 0b01000101,
                 0b01100001, 0b00111001, 0b00100011,
                 0b00000011, 0b11110001, 0b00000001,
                 0b00100001, 0b11111111 );

# Set RPi pin 11 to be an OUTPUT
Device::BCM2835::gpio_fsel($SCLK, BCM2835_GPIO_FSEL_OUTP);
# Set RPi pin 10 to be an OUTPUT
Device::BCM2835::gpio_fsel($MOSI, BCM2835_GPIO_FSEL_OUTP);
# Set RPi pin 9 to be an INPUT
Device::BCM2835::gpio_fsel($MISO, BCM2835_GPIO_FSEL_INPT);
# Set RPi pin 24 to be an OUTPUT
Device::BCM2835::gpio_fsel($CS, BCM2835_GPIO_FSEL_OUTP);

# prepare the edge
Device::BCM2835::gpio_write($CS, 1);
Device::BCM2835::gpio_write($SCLK, 0);

# subroutine sendValue
sub sendValue {
 # send value
 my $i = 0;
 my $value;
 ($value) = @_;
 while ($i < 8) {
   if ($value & 0x80) {
     Device::BCM2835::gpio_write($MOSI, 1);
   } else {
     Device::BCM2835::gpio_write($MOSI, 0);
   }
   # generate falling edge for the clock signals
   Device::BCM2835::gpio_write($SCLK, 1);
   Device::BCM2835::gpio_write($SCLK, 0);
   $value <<= 1; # shift bit 1 position to the left
   $i ++;
 }
}

# subroutine sendSPI
sub sendSPI {
 # CS active (LOW-Aktiv)
 Device::BCM2835::gpio_write($CS, 0);

 my($opcode, $addr, $data);
 ($opcode, $addr, $data) = @_;

 $test = &sendValue($opcode); # send OP-Code
 $test = &sendValue($addr);   # send address
 $test = &sendValue($data);   # send data

 # CS not active
 Device::BCM2835::gpio_write($CS, 1);
}

# Initialise MCP23S17
$test = &sendSPI($SPI_SLAVE_ADDR, $SPI_IODIRB, 0x00); # GPPIOB as INPUT
$test = &sendSPI($SPI_SLAVE_ADDR, $SPI_GPIOB, 0x00);  # Reset GPIOB
$test = &sendSPI($SPI_SLAVE_ADDR, $SPI_IODIRA, 0x00); # GPPIOA as INPUT
$test = &sendSPI($SPI_SLAVE_ADDR, $SPI_GPIOA, 0x00);  # Reset GPIOA

# Send Data
$test = &sendSPI($SPI_SLAVE_ADDR, $SPI_GPIOB, $output10[$param1]);
$test = &sendSPI($SPI_SLAVE_ADDR, $SPI_GPIOA, $output1[$param2]);

Das großartige Tutorial von Erik Bartmann welches sich hier findet, hat mir sehr geholfen meinen Code zu erstellen. Noch mehr Informationen gibt es auf seiner Website unter http://erik-bartmann.de.

2 Gedanken zu „7 Segment Anzeige am MCP23S17

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.