Kampis Elektroecke

Multiplexer für Siebensegmentanzeigen

Siebensegmentanzeigen eignen sich wunderbar als leicht umsetzbare Anzeige für z. B. Messwerte oder Statuswerte. Zum Ansteuern der kompletten Anzeige werden insgesamt sieben Datenleitungen und eine gemeinsame Leitung (je nach Anzeigentyp entweder die Masse als Kathode K oder die Betriebsspannung über Anode A) verwendet.

Durch die Verwendung von mehreren Anzeigen können mehrstellige Zahlen dargestellt werden. Da die Ansteuerung einer einzelnen Anzeige bis zu acht Leitungen am Steuerchip benötigt, werden die einzelnen Anzeigen durch einen Multiplexer nacheinander ein- und ausgeschaltet. Wird dieser Vorgang schnell genug wiederholt, ergibt sich für das menschliche Auge den Eindruck, als ob beide Anzeigen aktiv sind.

Wird durch den Multiplexer lediglich die gemeinsame Leitung eines Displays geschaltet, so verringert sich die Anzahl der benötigten Anschlussleitungen von Displays \cdot 8 auf Displays + 7.

Schauen wir uns mal an, wie ein einfacher Multiplexer für zwei Siebensegmentanzeigen in VHDL entworfen werden kann. Die verwendete Siebensegmentanzeige verwendet für jedes Element eine gemeinsame Kathode, die über einen Schmitt-Trigger auf Masse geschaltet werden muss.

Über einen Puls an der CAT-Leitung wird die jeweils aktive Anzeige gewechselt. Für den Multiplexer wird also erst einmal ein Timer benötigt, der die CAT-Leitung in bestimmten Abständen ein- und ausschaltet. Dies soll über das Signal Strobe geschehen.

process(Clock, nReset)
    variable RefreshCounter : INTEGER := 0;
begin
    if(nReset = '0') then
        RefreshCounter := 0;
        Strobe_Int <= '0';
    else
        if(rising_edge(Clock)) then
            if(RefreshCounter < REFRESH) then
                RefreshCounter := RefreshCounter + 1;
            else
                RefreshCounter := 0;
                Strobe_Int <= not Strobe_Int;
            end if;
        end if;
    end if;        
end process;

Strobe <= Strobe_Int;

Abhängig von dem Zustand des Signals Strobe_Int werden die jeweiligen vier Bit eines Datenbytes genutzt und als passendes Muster auf den sieben Datenleitungen ausgegeben:

process(Clock, nReset)
begin
    if(nReset = '0') then
        Anode <= (others => '0');
    elsif(rising_edge(Clock)) then
        case DisplayData is
            when "0000" => Anode <= "0111111";   
            when "0001" => Anode <= "0000110";
            when "0010" => Anode <= "1011011"; 
            when "0011" => Anode <= "1001111";
            when "0100" => Anode <= "1100110"; 
            when "0101" => Anode <= "1101101"; 
            when "0110" => Anode <= "1111101"; 
            when "0111" => Anode <= "0000111";
            when "1000" => Anode <= "1111111";
            when "1001" => Anode <= "1101111";
            when others => Anode <= (others => '0');
        end case;
    end if;
end process;

DisplayData <= Data(7 downto 4) when Strobe_Int = '1' else Data(3 downto 0);

Die Beschreibung für den vollständige Multiplexer sieht damit folgendermaßen aus:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Multiplexer is
    Generic (   REFRESH : INTEGER := 10000
                );
    Port ( Clock    : in STD_LOGIC;
           nReset   : in STD_LOGIC;
           Data     : in STD_LOGIC_VECTOR(7 downto 0);
           Anode    : out STD_LOGIC_VECTOR(6 downto 0);
           Strobe   : out STD_LOGIC
           );
end Multiplexer;

architecture Multiplexer_Arch of Multiplexer is

    signal DisplayData      : STD_LOGIC_VECTOR(3 downto 0)  := (others => '0');

    signal Strobe_Int       : STD_LOGIC := '0';

begin

    process(Clock, nReset)
        variable RefreshCounter : INTEGER := 0;
    begin
        if(nReset = '0') then
            RefreshCounter := 0;
        else
            if(rising_edge(Clock)) then
                if(RefreshCounter < REFRESH) then
                    RefreshCounter := RefreshCounter + 1;
                else
                    RefreshCounter := 0;
                    Strobe_Int <= not Strobe_Int;
                end if;
            end if;
        end if;        
    end process;

    process(Clock, nReset)
    begin
        if(nReset = '0') then
            Anode <= (others => '0');
        elsif(rising_edge(Clock)) then
            case DisplayData is
                when "0000" => Anode <= "0111111";   
                when "0001" => Anode <= "0000110";
                when "0010" => Anode <= "1011011"; 
                when "0011" => Anode <= "1001111";
                when "0100" => Anode <= "1100110"; 
                when "0101" => Anode <= "1101101"; 
                when "0110" => Anode <= "1111101"; 
                when "0111" => Anode <= "0000111";
                when "1000" => Anode <= "1111111";
                when "1001" => Anode <= "1101111";
                when others => Anode <= (others => '0');
            end case;
        end if;
    end process;

    Strobe <= Strobe_Int;
    DisplayData <= Data(7 downto 4) when Strobe_Int = '1' else Data(3 downto 0);

end Multiplexer_Arch;

Der fertige Multiplexer soll abschließend genutzt werden um einen Sekundenzähler zu realisieren. Dazu wird ein 125 MHz Takt für die Schaltung heruntergeteilt, ein Zähler inkrementiert und der Wert für die Zehner-, bzw. Einerstellen an den Multiplexer weiter gegeben.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Top is
    Generic (   REFRESH : INTEGER := 1000
                );
    Port (  Clock    : in STD_LOGIC;
            nReset   : in STD_LOGIC;
            Kathode  : out STD_LOGIC;
            Anode    : out STD_LOGIC_VECTOR (6 downto 0)
            );
end Top;

architecture Top_Arch of Top is

    signal First        : STD_LOGIC_VECTOR(3 downto 0) := (others => '0');
    signal Second       : STD_LOGIC_VECTOR(3 downto 0) := (others => '0');

    component Multiplexer is
        Generic (   REFRESH : INTEGER := 10000
                    );
        Port ( Clock    : in STD_LOGIC;
               nReset   : in STD_LOGIC;
               Data     : in STD_LOGIC_VECTOR(7 downto 0);
               Anode    : out STD_LOGIC_VECTOR(6 downto 0);
               Strobe   : out STD_LOGIC
               );
    end component Multiplexer;

begin

    Segment : component Multiplexer generic map (   REFRESH => REFRESH
                                                    )
                                    port map ( Clock => Clock,
                                               Data => Second & First,
                                               nReset => nReset,
                                               Anode => Anode,
                                               Strobe => Kathode
                                               );

    process(Clock, nReset)
        variable Counter    : INTEGER := 0;
        variable Seconds_E  : INTEGER := 0;
        variable Seconds_Z  : INTEGER := 0;
    begin
        if(nReset = '0') then
            Counter := 0;
            Seconds_E := 0;
            Seconds_Z := 0;
        elsif(rising_edge(Clock)) then
            if(Counter < 125000000) then
                Counter := Counter + 1;
            else
                Counter := 0;
                
                if(Seconds_E < 9) then
                    Seconds_E := Seconds_E + 1;
                else
                    Seconds_E := 0;
                    
                    if(Seconds_Z < 9) then
                        Seconds_Z := Seconds_Z + 1;
                    else
                        Seconds_Z := 0;
                    end if;
                end if;
            end if;
            
            First <= STD_LOGIC_VECTOR(to_unsigned(Seconds_E, First'length));
            Second <= STD_LOGIC_VECTOR(to_unsigned(Seconds_Z, First'length));
            
        end if;
    end process;
end Top_Arch;

Das fertige Design kann anschließend auf das FPGA übertragen und ausprobiert werden.

Ihr findet das komplette Projekt GitHub-Repository.

Schreibe einen Kommentar

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