Skip to content

Instantly share code, notes, and snippets.

@jerivas
Last active December 21, 2015 19:59
Show Gist options
  • Save jerivas/6358214 to your computer and use it in GitHub Desktop.
Save jerivas/6358214 to your computer and use it in GitHub Desktop.
Contador de números primos.
;Contador de numeros primos
;Jose Eduardo Rivas Melgar RM100161
;David Antonio Escobar Contreras EC100119
;Ángel Gerardo Moreno Galán MG070209
;El contador de numeros primos permite iterar sobre los numeros primos menores
;que 100 usando dos pushbuttons, uno para moverse de forma ascendente y otro
;para descendente. El resultado se muestra en dos displays de 7 segmentos
;multiplexados.
;En realidad, el programa itera sobre los datos que esten guardados en la
;direccion 200h a la 218h (25 en total). Para cargar los numeros primos en esa
;direccion, se recomienda importar el archivo MCH adjunto.
;Notese que los datos se deben guardar en formato BCD empaquetado.
title "Contador de numeros primos"
list p=18f4550
#include <p18f4550.inc>
;Directivas para activar los bits de configuracion
config FOSC = INTOSCIO_EC ;Oscilador Interno, Puerto A RA6 activo,
config WDT = OFF ;Watchdog timer apagado
config PBADEN = OFF ;Parte baja del puerto B digitales
config MCLRE = ON ;MCLRE Disponible
config DEBUG = ON ;Modo de depuracion disponible
config LVP = OFF ;Fuente de ISCP apagada
;Definicion de constantes utiles
#define btn_next INTCON,INT0IF ;Botón ascendente en PORTB0
#define btn_prev INTCON3,INT1IF ;Botón descendente en PORTB1
#define disp_1 LATB,4 ;Habilitador de display 1 en PORTB4
#define disp_2 LATB,5 ;Habilitador de display 2 en PORTB5
#define display LATD ;Codigo de 7 segmentos en PORTD
cblock
tmp ;Reservar memoria para una variable temporal
endc
org 0
goto init ;En RESET, ir a la rutina de inicialización
;-----------------------
;RUTINAS DE INTERRUPCION
;-----------------------
org 0x08 ;Direccion 08 donde apunta el PC cuando hay interrupcion
bcf INTCON,GIE ;Inhabilitar interrupciones. Evita anidamiento
test_next:
btfsc btn_next ;Se activó el botón de siguiente?
goto test_prev ;No: Probar si fue el botón de anterior
movlw .50 ;Si: Mover 50 a W
call delay ;Retardo proporcional a W
btfsc btn_next ;Sigue presionado el boton después del retardo?
goto back_to_main ;No: Fue rebote, no hacer nada
movlw 18 ;Si: Mover 18h a W para comparar
cpfseq FSR0L ;El puntero llego al último primo?
goto inc_FSR0 ;No: Incrementar puntero
clrf FSR0L ;Si: Apuntar el puntero al primer primo
goto back_to_main ;Volver al programa principal
test_prev:
btfsc btn_prev ;Se activó el botón de anterior?
goto back_to_main ;No: No hacer nada, volver al programa principal
call delay ;Retardo proporcional a W
btfsc btn_prev ;Sigue presionado el boton después del retardo?
goto back_to_main ;No: Fue rebote, no hacer nada
tstfsz FSR0L ;Si: Probar, el puntero llegó a cero?
goto dec_FSR0 ;No: Decrementar el puntero
lfsr FSR0,218 ;Si: Apuntar el puntero al último primo
back_to_main:
bcf btn_next ;Limpiar la bandera de botón siguiente
bcf btn_prev ;Limpiar la bandera de botón anterior
retfie ;Regresar de la interrupcion (tambien habilita GIE)
;--------------
;INICIALIZACION
;--------------
init:
clrf display ;Inicializar Puerto D
clrf TRISD ;Configurar todo el puerto D como salida
movlw b'00000011'
movwf TRISB ;PORTB0 y 1 son entradas, PORTB4 y 5 son salidas
bcf disp_1 ;Deshabilitar el display 1
bcf disp_2 ;Deshabilitar el display 2
lfsr FSR0,200 ;Apuntar FSR0 a la direccion 200h donde estan los primos
bcf INTCON2,INTEDG0 ;INT0 Activada en flanco descendente
bcf INTCON2,INTEDG1 ;INT1 Activada en flanco descendente
bsf INTCON,GIE ;Habilitar interrupciones globalmente
bsf INTCON,PEIE ;Habilitar interrupciones perifericas
bsf INTCON,INT0IE ;Habilitar interrupcion INT0
bsf INTCON3,INT1IE ;Habilitar interrupcion INT1
;-----------------------------------------------------------------
;Programa principal:
;Rutina que muestra el conteo actual en dos displays multiplexados
;-----------------------------------------------------------------
multiplex_displays:
movf INDF0,W ;En W, obtener el primo actual
movwf tmp ;Copiarlo a tmp
andlw 0x0F ;En W, obtener solo las unidades
call bin_to_seg ;Convertirlo a codigo 7 segmentos
bcf disp_2 ;Apagar el display 2
movwf display ;Preparar el código a mostrar
bsf disp_1 ;Mostrarlo en display 1
movlw .25 ;Cargar 25 en W
call delay ;Retardo proporcional a W
swapf tmp ;Hacer swap en tmp de decenas y unidades
movf tmp,W ;En W, obtener el primo ya intercambiado
andlw 0x0F ;Discrimiar de nuevo, esta vez decenas
call bin_to_seg ;Convertirlo a codigo 7 segmentos
bcf disp_1 ;Apagar el display 1
movwf display ;Preparar el código a mostrar
bsf disp_2 ;Mostrarlo en display 2
movlw .25 ;Cargar 25 en W
call delay ;Retardo proporcional a W
goto multiplex_displays ;Repetir
;------------------
;RUTINAS AUXILIARES
;------------------
inc_FSR0:
incf FSR0L
goto back_to_main
dec_FSR0:
decf FSR0L
goto back_to_main
;-----------------------------------------------------
;Binario a 7 segmentos
;Convierte el valor binario en W en codigo 7 segmentos
;El codigo adecuado se retorna en W
;-----------------------------------------------------
bin_to_seg:
mullw .2 ;Multiplicar Wx2. El resultado se guarda en PROD
movf PRODL,W ;Copiar el resultado de PRODL a W
addwf PCL,F ;El puntero de programa se desplaza de acuerdo al valor
;que esta en W. Esto selecciona el cod. adecuado.
;Formato de bits del codigo 7 seg: xgfedcba
retlw b'00111111' ;0
retlw b'00000110' ;1
retlw b'01011011' ;2
retlw b'01001111' ;3
retlw b'01100110' ;4
retlw b'01101101' ;5
retlw b'01111101' ;6
retlw b'00000111' ;7
retlw b'01111111' ;8
retlw b'01101111' ;9
;------------------------------------------------------------
;Delay:
;Crea una espera proporcional al valor de W cuando es llamado
;------------------------------------------------------------
cblock
del0,del1,del2 ;Reservar memoria para tres variables
endc
delay:
movwf del2 ;del2 = W
ldel:
movlw .15
movwf del1 ;del1 = 15
movlw .207
movwf del0 ;del0 = 207
decfsz del0,F ;Decrementar. del0 = 0?
goto $ + 2 ;No: bajar dos lineas
decfsz del1,F ;Si: Decrementar. del1 = 0?
goto $ - 3 ;Subir tres lineas
decfsz del2,F ;Decrementar. del2 = 0?
goto ldel ;No: ir a ldel
return ;Si: Fin de subrutina
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment