;==============================================================================
; 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]
To embed this project on your website, copy the following code and paste it into your website's HTML: