;==============================================================================
; PROYECTO: Contador Multiplexado de 2 Dígitos
; Placa SimuPIC - PIC16F628A
; Objetivo: Contar de 50 hasta 99 de a 3, luego volver a 50 y de a 1 bajar hasta 0.
;==============================================================================
;------------------------------------------------------------------------------
; DEFINICIÓN DE VARIABLES (Mapa de Memoria RAM - Banco 0)
;------------------------------------------------------------------------------
UNI     EQU     0x20    ; Registro para las Unidades (0 al 9)[cite: 2]
DEC     EQU     0x21    ; Registro para las Decenas (0 al 9)[cite: 2]
MUXCNT  EQU     0x22    ; Contador de vueltas para el parpadeo rápido[cite: 2]
DIVCNT  EQU     0x23    ; Divisor para ralentizar el avance de los números[cite: 2]
DLY     EQU     0x24    ; Tiempo de retraso de cada display[cite: 2]
MODO    EQU     0x25    ; 0 = Sube de a 3 / 1 = Baja de a 1

;------------------------------------------------------------------------------
; VECTOR DE INICIO (RESET)
;------------------------------------------------------------------------------
        ORG     0            ; Inicio de la memoria de programa[cite: 2]
        GOTO    CONFIG_MICRO ; Salta a la inicialización del sistema[cite: 2]

;------------------------------------------------------------------------------
; SECCIÓN DE CONFIGURACIÓN ELECTRÓNICA
;------------------------------------------------------------------------------
CONFIG_MICRO:
        ; --- Gestión de Bancos de Memoria RAM ---
        BSF     STATUS, RP0  ; Entra al BANCO 1 (Configuración)[cite: 2]
        CLRF    TRISB        ; Todo el Puerto B como salida (segmentos a-g)[cite: 2, 3]
        MOVLW   b'11111100'  ; RA0 y RA1 como salidas (comunes de los displays)[cite: 2, 3]
        MOVWF   TRISA        ; RA2 a RA7 como entradas[cite: 2]
        BCF     STATUS, RP0  ; Regresa al BANCO 0 (Operaciones)[cite: 2]

        ; --- Configuración de Pines Digitales ---
        MOVLW   b'00000111'  ; Apaga los comparadores analógicos internos[cite: 2]
        MOVWF   CMCON        ; Habilita el Puerto A como digital[cite: 2]

        ; --- Inicialización de Registros (Arranque en 50) ---
        CLRF    PORTA        ; Apaga displays[cite: 2]
        CLRF    PORTB        ; Apaga segmentos[cite: 2]
        CLRF    UNI          ; Unidades = 0
        MOVLW   .5           ; Carga el 5 en W
        MOVWF   DEC          ; Decenas = 5 (Número inicial: 50)
        CLRF    MUXCNT       ; Inicializa control de multiplexación en 0[cite: 2]
        CLRF    DIVCNT       ; Inicializa ralentizador en 0[cite: 2]
        CLRF    MODO         ; Inicia en MODO = 0 (subiendo de a 3)

;------------------------------------------------------------------------------
; BUCLE PRINCIPAL: REFRESCO EN PANTALLA (MULTIPLEXACIÓN)
;------------------------------------------------------------------------------
loop
        ; --- PASO 1: Mostrar Unidades ---
        CLRF    PORTA        ; Evita el efecto fantasma[cite: 2]
        MOVF    UNI, W       ; Copia UNI en W[cite: 2]
        CALL    tabla        ; Traduce a 7 segmentos[cite: 2]
        MOVWF   PORTB        ; Envía patrón al Puerto B[cite: 2]
        BSF     PORTA, 0     ; Enciende display derecho (Unidades)[cite: 2, 3]
        CALL    demora       ; Retardo de brillo[cite: 2]

        ; --- PASO 2: Mostrar Decenas ---
        CLRF    PORTA        ; Apaga displays[cite: 2]
        MOVF    DEC, W       ; Copia DEC en W[cite: 2]
        CALL    tabla        ; Traduce a 7 segmentos[cite: 2]
        MOVWF   PORTB        ; Envía patrón al Puerto B[cite: 2]
        BSF     PORTA, 1     ; Enciende display izquierdo (Decenas)[cite: 2, 3]
        CALL    demora       ; Retardo de brillo[cite: 2]

        ; --- PASO 3: Control de Tiempo del Parpadeo ---
        INCFSZ  MUXCNT, F    ; Incrementa MUXCNT hasta desbordar en 256[cite: 2]
        GOTO    loop         ; Sigue multiplexando[cite: 2]

        ; --- PASO 4: Ralentizador del Reloj ---
        INCF    DIVCNT, F    ; Incrementa divisor de tiempo[cite: 2]
        MOVLW   d'3'         ; Velocidad del conteo[cite: 2]
        SUBWF   DIVCNT, W    ; Resta DIVCNT - 3[cite: 2]
        BTFSS   STATUS, Z    ; ¿Llegó a 3?[cite: 2]
        GOTO    loop         ; Si no llegó, sigue refrescando pantalla[cite: 2]
        CLRF    DIVCNT       ; Reinicia divisor y actualiza el contador[cite: 2]

;------------------------------------------------------------------------------
; LÓGICA DE CONTROL DEL CONTADOR (SUBIDA DE A 3 / BAJADA DE A 1)
;------------------------------------------------------------------------------
        BTFSC   MODO, 0      ; Revisa MODO: si es 0 sigue a SUBIENDO; si es 1 salta
        GOTO    BAJANDO

; --- ETAPA 1: CONTAR DE 50 A 99 DE A 3 ---
SUBIENDO:
        ; Verificar si ya estamos mostrando el 99
        MOVLW   .9
        SUBWF   DEC, W       ; ¿DEC == 9?
        BTFSS   STATUS, Z
        GOTO    SUMAR_3      ; Si DEC no es 9, suma 3 normalmente
        MOVLW   .9
        SUBWF   UNI, W       ; ¿UNI == 9?
        BTFSS   STATUS, Z
        GOTO    SUMAR_3      ; Si UNI no es 9, suma 3 normalmente

        ; Si ya llegó a 99, vuelve a 50 y pasa a modo bajada (MODO = 1)
        MOVLW   .5
        MOVWF   DEC          ; Decenas = 5
        CLRF    UNI          ; Unidades = 0 (Muestra 50)
        MOVLW   .1
        MOVWF   MODO         ; Cambia a MODO = 1 (bajando de a 1)
        GOTO    loop

SUMAR_3:
        MOVLW   .3
        ADDWF   UNI, F       ; Suma 3 a las unidades (UNI = UNI + 3)
        MOVLW   .10
        SUBWF   UNI, W       ; Resta UNI - 10 (Carry C=1 si UNI >= 10)
        BTFSS   STATUS, C    ; ¿UNI es mayor o igual a 10?
        GOTO    loop         ; Si es menor a 10, vuelve a mostrar el número

        ; Ajuste decimal cuando UNI >= 10
        MOVWF   UNI          ; W contiene (UNI - 10), lo guarda como nuevas unidades
        INCF    DEC, F       ; Suma 1 a las decenas
        MOVLW   .10
        SUBWF   DEC, W       ; ¿DEC llegó a 10 (es decir, superó 99)?
        BTFSS   STATUS, Z
        GOTO    loop         ; Si no llegó a 10, vuelve al bucle

        ; Si al sumar 3 superó 99 (98 + 3 = 101), fija el límite en 99
        MOVLW   .9
        MOVWF   DEC          ; Decenas = 9
        MOVLW   .9
        MOVWF   UNI          ; Unidades = 9 (Muestra 99)
        GOTO    loop

; --- ETAPA 2: CONTAR DE 50 A 00 DE A 1 ---
BAJANDO:
        ; Verificar si ya estamos mostrando el 00
        MOVF    DEC, W       ; Copia DEC en W (activa Z si es 0)
        BTFSS   STATUS, Z    ; ¿DEC == 0?
        GOTO    RESTAR_1     ; Si no es 0, resta 1 normalmente
        MOVF    UNI, W       ; Copia UNI en W (activa Z si es 0)
        BTFSS   STATUS, Z    ; ¿UNI == 0?
        GOTO    RESTAR_1     ; Si no es 0, resta 1 normalmente

        ; Si ya llegó a 00, reinicia todo el ciclo en 50 subiendo de a 3
        MOVLW   .5
        MOVWF   DEC          ; Decenas = 5
        CLRF    UNI          ; Unidades = 0 (Muestra 50)
        CLRF    MODO         ; Vuelve a MODO = 0 (subiendo de a 3)
        GOTO    loop

RESTAR_1:
        DECF    UNI, F       ; Resta 1 a las unidades (UNI = UNI - 1)
        MOVLW   0xFF         ; Si UNI era 0, al restar 1 pasa a 255 (0xFF)
        SUBWF   UNI, W       ; ¿UNI == 0xFF?
        BTFSS   STATUS, Z
        GOTO    loop         ; Si no hubo desborde, vuelve al bucle

        ; Ajuste decimal cuando UNI baja de 0 a 9
        MOVLW   .9
        MOVWF   UNI          ; Unidades = 9
        DECF    DEC, F       ; Resta 1 a las decenas
        GOTO    loop

;------------------------------------------------------------------------------
; TABLA DE TRADUCCIÓN: SALTO INDEXADO (0 al 9 a 7 Segmentos)
;------------------------------------------------------------------------------
tabla
        ADDWF   PCL, F       ; Salto indexado según el valor de W[cite: 2]
        RETLW   b'00111111'  ; '0'[cite: 2]
        RETLW   b'00000110'  ; '1'[cite: 2]
        RETLW   b'01011011'  ; '2'[cite: 2]
        RETLW   b'01001111'  ; '3'[cite: 2]
        RETLW   b'01100110'  ; '4'[cite: 2]
        RETLW   b'01101101'  ; '5'[cite: 2]
        RETLW   b'01111101'  ; '6'[cite: 2]
        RETLW   b'00000111'  ; '7'[cite: 2]
        RETLW   b'01111111'  ; '8'[cite: 2]
        RETLW   b'01101111'  ; '9'[cite: 2]

;------------------------------------------------------------------------------
; SUBRUTINA DE RETRASO INTERNO (Control de brillo)
;------------------------------------------------------------------------------
demora
        MOVLW   0x40         ; Duración del encendido de cada display[cite: 2]
        MOVWF   DLY          ; Guarda en DLY[cite: 2]
demora1
        DECFSZ  DLY, F       ; Decrementa hasta 0[cite: 2]
        GOTO    demora1      ; Repite bucle[cite: 2]
        RETURN               ; Vuelve al programa principal[cite: 2]
        
        END                  ; Fin del programa[cite: 2]

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: