Multiplexado de displays de siete segmentos con VHDL

Displays de siete segmentos

Cuando un diseño utiliza más de un display de siete segmentos es interesante multiplexarlos para ahorrar en conexiones. Si no lo hacemos así, para controlar cuatro displays necesitaríamos 32 conexiones al microcontrolador si es que queremos manejar directamente los displays sin ningún integrado de por medio. Vamos ver cómo funciona este multiplexado y cómo se puede implementar en una FPGA usando VHDL.

Existen dispositivos que empaquetan varios displays que son muy cómodos de usar. En este artículo, como ejemplo usaremos uno de cuatro displays. Sin embargo esta técnica puede usarse con varios displays sueltos. En el siguiente esquema se presenta la manera correcta de hacer las conexiones mediante transistores configurados en emisor común para funcionar como interruptores.

4 displays

Las entradas D0 a D3 permiten seleccionar qué display queremos activar en cada momento, mientras que las entradas A a G (y DP) permiten seleccionar qué leds se han de encender para mostrar el dígito en dicho display (es decir, son comunes a los cuatro displays). ¿Esto quiere decir que, de los cuatro, sólo podemos mostrar un dígito a la vez? Efectivamente, así es. El truco está en que podemos ir activando un display tras otro de forma cíclica a una velocidad suficiente como para engañar al ojo creando la ilusión de estar viendo los cuatro dígitos al mismo tiempo. Para ello, el ciclo de refresco (el tiempo que trascurre desde que se activa el primer display hasta que se desactiva el último) ha de estar entre 1 milisegundo (incluso menos) y 16 milisegundos para que no se note ningún tipo de parpadeo. Así, en nuestro caso cada display estará activo un cuarto del tiempo completo de refresco (ya que son 4 displays).

Cronograma display multiplexado

Por lo tanto, el circuito que vamos a diseñar tiene que tener un control preciso sobre el tiempo. En el artículo anterior ya vimos como generar una señal de reloj de 1Hz a partir de un reloj de 50MHz usando un contador. En esta ocasión vamos a utilizar la misma técnica para obtener una señal para el refresco de los displays. Usando un contador para dividir los 50MHz del reloj de la placa entre 100.000 obtenemos una frecuencia de 500Hz, es decir, un periodo de 2 milisegundos. El siguiente código VHDL muestra los dígitos 0123 en el display.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity muxdisplay_top is
port (
    clk50mhz: 	    in STD_LOGIC;
    display: 	    out STD_LOGIC_VECTOR(6 downto 0);
    cur_display:    out STD_LOGIC_VECTOR(3 downto 0)
);
end muxdisplay_top;

architecture beh of muxdisplay_top is
    -- 50Mzh/100000=500Hz
    constant max_refresh_count: INTEGER := 100000; 
    signal refresh_count: INTEGER range 0 to max_refresh_count;
    signal refresh_state: STD_LOGIC_VECTOR(1 downto 0) := (others => '0');
    signal display_sel: STD_LOGIC_VECTOR(3 downto 0) := (others => '0');
	
begin
    cur_display <= display_sel;

    gen_clock: process(clk50mhz)
    begin
        if clk50mhz'event and clk50mhz='1' then
	    -- contador 500Hz (para refresco del display)
	    if refresh_count < max_refresh_count then
		refresh_count <= refresh_count + 1;
	    else
		refresh_state <= refresh_state + 1;
		refresh_count <= 0; 
            end if; 
        end if; 
    end process; 

    show_display: process(refresh_state) 
        begin -- selección del display 
            case refresh_state is 
                when "00" => 
                    display_sel <= "1110"; -- display 0 
                when "01" => 
                    display_sel <= "1101"; -- display 1 
                when "10" => 
                    display_sel <= "1011"; -- display 2 
                when "11" => 
                    display_sel <= "0111"; -- display 3 
                when others => 
                    display_sel <= "1111"; 
            end case; 

            -- mostrar digitos 
            case display_sel is 
                when "1110" => 
		    display <= "1000000"; -- 0 
                when "1101" => 
		    display <= "1111001"; -- 1 
                when "1011" => 
		    display <= "0100100"; -- 2 
                when "0111" => 
		    display <= "0110000"; -- 3 
                when others =>
		    display <= "1111111"; 
	    end case;
	end process;
end beh;

La señal refresh_count hace la función de contador, es decir, que se incrementa en cada ciclo de reloj y cuando llega a 100.000 se resetea y vuelve a comenzar desde 0. Cuando esto ocurre, la señal refresh_state se incrementa. Como es una señal de dos bits, puede tomar uno de los siguientes valores: 00, 01, 10, 11. Dependiendo del valor de esta señal se activará (a nivel bajo) la señal cur_display correspondiente, que se encarga de seleccionar cuál de los cuatro displays ha de activarse. Como ves, se trata de un demultiplexor de 2 a 4. El resto del código es bastante comprensible. Dependiendo del display que esté seleccionado en cada momento, se muestra un dígito u otro activando los leds correspondientes en el bus (o bundle en la jerga de VHDL) de salida llamado display.

En la siguiente imagen os dejo las conexiones que he realizado en pin planner de Quartus para la tarjeta FPGA EP1C3T144 de la que ya hablamos en otro artículo anterior.

Asignación de pines del display

Este es nuestro display tras configurar la FPGA con este código VHDL.

Display siete segmentos multiplexado en FPGA con VHDL

Sé el primero en comentar en "Multiplexado de displays de siete segmentos con VHDL"

Deja un comentario.

Tu dirección de correo no será publicada.


*