En este proyecto se implementa un contador digital de 00 a 99 utilizando el microcontrolador PIC18F4550, dos displays de 7 segmentos y dos pulsadores. El sistema permite incrementar y decrementar el valor mostrado mediante los pines RA0 y RA1, respectivamente. Además, se emplea multiplexación para controlar ambos displays con un número reducido de pines.
Este tipo de implementación es fundamental en sistemas embebidos, ya que combina control de entradas, procesamiento lógico y manejo eficiente de salidas.
CIRCUITO

Estructura general del programa
El programa se divide en tres bloques principales:
Entrada
Se utilizan dos pulsadores conectados a los pines RA0 y RA1. Estos permiten interactuar con el sistema:
- RA0 incrementa el contador
- RA1 decrementa el contador
Procesamiento
El valor del contador se almacena en una variable de tipo unsigned char, permitiendo valores de 0 a 99. Se implementa lógica de conteo circular para evitar desbordamientos.
Salida
Se utilizan dos displays de 7 segmentos controlados mediante multiplexación, lo que permite mostrar dos dígitos utilizando un solo puerto de datos.
Configuración de pines
Configuración digital
ADCON1 = 0x0F;
Esta instrucción configura todos los pines como digitales, lo cual es necesario para que RA0 y RA1 funcionen correctamente como entradas.
Dirección de puertos
TRISD = 0x00;
TRISE = 0x00;
TRISA = 0xFF;
- PORTD se usa para los segmentos
- PORTE controla qué display está activo
- PORTA se usa para leer los pulsadores
Lógica del contador
Incremento
contador++;
if(contador > 99) contador = 0;
Cuando se presiona RA0, el contador aumenta en una unidad. Si supera 99, vuelve a 0, implementando un conteo cíclico.
Decremento
if(contador == 0)
contador = 99;
else
contador--;
Al presionar RA1, el contador disminuye. Si está en 0, pasa a 99, manteniendo el ciclo.
Antirrebote de botones
__delay_ms(50);
while(PORTAbits.RA0 == 1);
Se implementa un retardo para evitar lecturas erráticas debido al rebote mecánico del pulsador. Además, se espera a que el botón sea liberado antes de continuar.
Control de los displays
Tabla de segmentos
El programa utiliza una tabla que define qué segmentos encender para cada número del 0 al 9.
const unsigned char tabla[10] = {...};
Cada valor representa la combinación de segmentos necesaria para mostrar un dígito.
Multiplexación
La multiplexación permite controlar ambos displays alternando rápidamente entre ellos:
- Se muestra la decena
- Se apaga el display
- Se muestra la unidad
PORTD = tabla[decena];
PORTEbits.RE1 = 1;
PORTD = tabla[unidad];
PORTEbits.RE0 = 1;
Este proceso ocurre continuamente, generando la ilusión de que ambos displays están encendidos simultáneamente.
PROGRAMA COMPLETO
#define _XTAL_FREQ 8000000
#include <xc.h>
// CONFIG (solo si NO usas config.c, si ya tienes config.c → borra esto)
#pragma config FOSC = HS
#pragma config WDT = OFF
#pragma config LVP = OFF
#pragma config PBADEN = OFF
#pragma config MCLRE = ON
// Tabla 7 segmentos (cátodo común)
const unsigned char tabla[10] = {
0x3F, // 0
0x06, // 1
0x5B, // 2
0x4F, // 3
0x66, // 4
0x6D, // 5
0x7D, // 6
0x07, // 7
0x7F, // 8
0x6F // 9
};
unsigned char contador = 0;
// -------- MOSTRAR EN DISPLAY --------
void mostrar(unsigned char num) {
unsigned char decena = num / 10;
unsigned char unidad = num % 10;
// DECENA
PORTE = 0x00;
PORTD = tabla[decena];
PORTEbits.RE1 = 1;
__delay_ms(5);
// UNIDAD
PORTE = 0x00;
PORTD = tabla[unidad];
PORTEbits.RE0 = 1;
__delay_ms(5);
}
// -------- MAIN --------
void main() {
ADCON1 = 0x0F; // TODO digital
TRISD = 0x00; // segmentos
TRISE = 0x00; // control displays
TRISA = 0xFF; // botones
PORTD = 0x00;
PORTE = 0x00;
contador = 0; // empieza en 00
while(1) {
// ---- RA0 INCREMENTA ----
if(PORTAbits.RA0 == 1) {
__delay_ms(50);
if(PORTAbits.RA0 == 1) {
contador++;
if(contador > 99) contador = 0;
while(PORTAbits.RA0 == 1);
}
}
// ---- RA1 DECREMENTA ----
if(PORTAbits.RA1 == 1) {
__delay_ms(50);
if(PORTAbits.RA1 == 1) {
if(contador == 0)
contador = 99;
else
contador--;
while(PORTAbits.RA1 == 1);
}
}
mostrar(contador);
}
}
Conclusión
Este proyecto demuestra cómo integrar entradas digitales, lógica de control y visualización en un sistema embebido. La multiplexación permite optimizar el uso de pines, mientras que la gestión de botones introduce conceptos clave como antirrebote y control de estado.
A partir de esta base, es posible escalar el diseño hacia aplicaciones más complejas como relojes digitales, interfaces de usuario o sistemas de monitoreo.