Display contador de 4 dígitos de 7 segmentos 0-9999


En esta entrada os enseñaré cómo hacer un contador de 0 a 9999 utilizando 4 displays de 7 segmentos (de cátodo común, en este caso).

Vamos a generar una librería para la visualización de los displays que nos sirva para los siguientes proyectos.

Cada uno de los displays tiene internamente 7 diodos leds para los caracteres y uno adicional para el punto. Todos estos leds tienen unidos sus cátodos o ánodos (esta característica se elige a la hora de comprar los displays) así que tendremos por cada display 7 líneas independientes para activar los leds y una común. Como queremos utilizar 4 displays, tendríamos en total 28 líneas de activación que nos ocuparían prácticamente todos los puertos disponibles del microcontrolador. Así que lo que vamos a hacer es multiplexar las patillas de los cátodos/ánodos. De esta manera lo que hacemos es encender sólo un display cada vez pero al hacerlo con una frecuencia alta, a la vista parecerá que los 4 displays están encendidos.

Para engañar al ojo humano pondremos una frecuencia de barrido superior a 50Hz.

display 7 segmentos

Display 7 segmentos de cátodo común

Es importante tener en cuenta la intensidad de salida que es capaz de dar nuestro microcontrolador, que en el caso del LPC1347 es de 4mA. Es suficiente para encender un led pero con muy poca intensidad (normalmente la intensidad óptima está entre 10 y 20mA). Para que los displays luzcan en todo su esplendor, vamos utilizar las salidas del micro para activar unos transistores que serán los encargados de conmutar la alimentación de leds, pudiendo por tanto alimentarlos con más intensidad.

Vamos a ver cómo quedaría el esquema electrónico:

esquema display 7 segmentos

Las líneas PIO0.4, PIO0.21,PIO0.22 y PIO0.23 serán las que activen los distintos displays.

Las líneas PIO1.31,PIO1.28, PIO1.27, PIO1.26, PIO1.25, PIO1.24 y PIO1.23 serán las que enciendan los distintos leds para formar el carácter deseado.

Para facilitar el trabajo de programación, he elegido que cada uno de los dos bloques de pines (activación del display y activación de led) esté íntegramente en el mismo puerto. Así con una instrucción podré cambiar el estado de todas las líneas que están en cada puerto.

Si te fijas en PIO0.4 verás que tiene una resistencia de pull-up. Esto es así porque esta salida y PIO0.5 son de tipo colector abierto y necesitan polarizarse para trabajar con ellas.

El montaje en la protoboard queda de la siguiente manera:

LPC1347 display 7 segmentos

Es interesante crear una librería con las funciones necesarias para el manejo de los displays, así hacer la integración en futuros proyectos nos resultará muy fácil. He creado un archivo llamado disp7seg.c y las definiciones de las funciones en el archivo disp7seg.h

Estos dos archivos los incluiremos en la carpeta del proyecto en el LPCXpresso IDE.

El archivo disp7seg.c quedaría de la siguiente manera:

#include "disp7seg.h"
#include "delay.h"
#include "chip.h"
void config7segm(void)
{
   Chip_GPIO_SetDir(LPC_GPIO_PORT,1,0x9F800000,1); //segmentos como salidas
   Chip_GPIO_SetDir(LPC_GPIO_PORT,0,0x00E00010,1); //cátodos displays como salidas
}
 
void Imprime7segm(uint16_t numero)
{
  uint8_t unidades, decenas, centenas, millares;
  uint32_t mascaraNum[10] = {
      0x97800000, //0
      0x82000000, //1
      0x99800000, //2
      0x9B000000, //3
      0x8E000000, //4
      0x1F000000, //5
      0x1F800000, //6
      0x92000000, //7
      0x9F800000, //8
      0x9F000000 //9
      };
 
   millares= numero / 1000;
   centenas=(numero - (millares*1000)) / 100;
   decenas=(numero - ( (millares*1000) + (centenas*100)) ) / 10;
   unidades=numero % 10;
   //unidades
   Chip_GPIO_ClearValue(LPC_GPIO_PORT, 0, 0x00E00010); //apago todos los cátodos
   Chip_GPIO_ClearValue(LPC_GPIO_PORT, 1, 0x9F800000); //apago todos los segmentos
 
   Chip_GPIO_SetValue(LPC_GPIO_PORT, 0, 0x00000010); //activo el cátodo del display
   Chip_GPIO_SetValue(LPC_GPIO_PORT, 1, mascaraNum[unidades]); //activo los segmentos del número
   _delay_ms(4);
 
   //decenas
   Chip_GPIO_ClearValue(LPC_GPIO_PORT, 0, 0x00E00010); //apago todos los cátodos
   Chip_GPIO_ClearValue(LPC_GPIO_PORT, 1, 0x9F800000); //apago todos los segmentos
 
   Chip_GPIO_SetValue(LPC_GPIO_PORT, 0, 0x00200000); //activo el cátodo del display
   Chip_GPIO_SetValue(LPC_GPIO_PORT, 1, mascaraNum[decenas]); //activo los segmentos del número
   _delay_ms(4);
 
   //centenas
   Chip_GPIO_ClearValue(LPC_GPIO_PORT, 0, 0x00E00010); //apago todos los cátodos
   Chip_GPIO_ClearValue(LPC_GPIO_PORT, 1, 0x9F800000); //apago todos los segmentos
 
   Chip_GPIO_SetValue(LPC_GPIO_PORT, 0, 0x00400000); //activo el cátodo del display
   Chip_GPIO_SetValue(LPC_GPIO_PORT, 1, mascaraNum[centenas]); //activo los segmentos del número
   _delay_ms(4);
 
   //millares
   Chip_GPIO_ClearValue(LPC_GPIO_PORT, 0, 0x00E00010); //apago todos los cátodos
   Chip_GPIO_ClearValue(LPC_GPIO_PORT, 1, 0x9F800000); //apago todos los segmentos
 
   Chip_GPIO_SetValue(LPC_GPIO_PORT, 0, 0x00800000); //activo el cátodo del display
   Chip_GPIO_SetValue(LPC_GPIO_PORT, 1, mascaraNum[millares]); //activo los segmentos del número
   _delay_ms(4);
 
}

La función delay de 4ms es importante. Como estamos encendiendo y apagando contínuamente los displays, necesitamos que permanezcan encendidos un tiempo para que el ojo pueda verlos correctamente. En este caso al tratarse de 4 displays, con una activación de 4ms cada uno tendríamos un periodo de refresco de 16ms, o lo que es lo mismo 62.5Hz por lo que no apreciaremos ningún parpadeo.

Para hacer un contador 0-9999 realizamos un sencillo código en la función principal:

#include "disp7seg.h"
#include "delay.h"
#include "chip.h"
 
int main(void) {
#if defined (__USE_LPCOPEN)
#if !defined(NO_BOARD_LIB)
    // Read clock settings and update SystemCoreClock variable
    SystemCoreClockUpdate();
 
    Board_Init();
    setSYSTICK(); 
    Board_LED_Set(0, true);   // Set the LED to the state of "On"
#endif
#endif
 
    SystemCoreClockUpdate();
    setSYSTICK();
 
    // Enter an infinite loop, just incrementing a counter
    uint16_t i=0;
    uint16_t num=0;
 
    Chip_GPIO_WriteDirBit(LPC_GPIO_PORT, 0, 7, true);
    Chip_GPIO_WritePortBit(LPC_GPIO_PORT, 0, 7, true);
 
    config7segm();
 
    while(1) {
    	if(num < 9999 ) num=0;
    	if(i > 10 ) {             // para que la cuenta sea visible, hacemos esta condición (aumentamos un número cada 10 veces que se muestra)
    		i=0;
    		num++;
        	Chip_GPIO_WritePortBit(LPC_GPIO_PORT, 0, 7, !Chip_GPIO_ReadPortBit(LPC_GPIO_PORT, 0, 7));	//cambia el estado del led de la placa
    	};
    	Imprime7segm(num);      //mostramos contínuamente el valor num en el display
    	i++;
    }
    return 0 ;
}

¡Ya tienes tu display funcionando! ¿Ha sido fácil, verdad?
Con esta función que hemos creado seguro que se te ocurren un montón de programas para hacer. Qué tal si te animas a hacer un voltímetro digitial utilizando un puerto del ADC?

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *