Autor Tema: Reloj Digital Como migrar un Codigo en Ensamblador del PIC16F84A al PIC16F628A  (Leído 23543 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado guero_j25

  • PIC10
  • *
  • Mensajes: 3
Hola, este es la primera vez que inicio un tema... sinceramente soy nuevo en esto de la programacion en Ensamblador, y me interesa mucho migrar el codigo del PIC16F84A al PIC16F628A de un Relog Digital que incluso ya he probado en Proteus ISIS.

Y por lo que he visto el PIC16F628A es mucho mejor y mas barato, ademas que yo tengo el PICKIT 2 y este no puede grabar en el PIC16F84A, es por eso que les pido su ayuda para migrarlo al PIC16F628A.


Agrego enlace, del proyecto completo Reloj Digital 12H PIC16F84A, (Debo aclarar que en la parte donde he puesto la Tableta PCB hecha en Proteus ARES, creo que por ahi tiene algunos detallitos que me faltan afinar... Por si alguien mas desea aportar con esta Ayuda, ya que es para todos...) espero les sea de mucha utilidad:


A las personas que quieran ayudarme en la conversion de este programa al PIC16F628A, favor de publicar el programa ya convertido para el PIC16F628A... de antemano les agradezco su Ayuda y Comprension. Saludos.

Aqui pongo el Codigo del programa completo...
Código: [Seleccionar]
;*************************************************************
; RELOJ DE 12 HORAS
;*************************************************************

LIST P=PIC16F84A ; Pic a usar
#INCLUDE <P16F84A.INC> ; Lista de etiquetas de microchip

__CONFIG    _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC      

FRAC_INI equ D'12' ; Constante para inicio cuenta de fracciones de segundo
SEGS_INI equ D'196' ; Constante para inicio cuenta de segundos
MINS_INI equ D'196' ; Constante para inicio cuenta de minutos
HORS_INI equ D'244' ; Constante para cuenta de horas
HORS_12H equ D'243' ; Constante para cuenta de horas

ADJMIN equ D'9' ; Número de "frac_sec" que se necesita sumar cada minuto
; para ajustar el tiempo
ADJHOR equ D'34' ; Número de "frac_sec" que se necesita restar cada hora
; para ajustar el tiempo
ADJDIA equ D'3' ; Número de "frac_sec" que se necesita sumar cada 12 horas
; para ajustar el tiempo

; Activación de RB1-3 para las entradas de los pulsadores
PULSADOR equ B'00001110' ; RB1, RB2 y RB3

; Asignación de banderas. Los pulsadores activos proporcionan un "1"
CHG equ H'03' ; Indica que se ha activado un pulsador o que es necesario
; actualizar los valores de la hora que tienen que mostrarse
; en los displays
PSEG equ H'04' ; Pulsador A, modo segundero.
PMIN equ H'05' ; Pulsador B, avance rápido minutos.
PHOR equ H'06' ; Pulsador C, avance rápido horas.
P_ON equ H'07' ; Un pulsador ha sido activado

DSPOFF equ B'11111111' ; Displays apagados (PORTA)
; gfedcbap
CERO equ H'7E' ; 01111110
UNO equ H'0C' ; 00001100
DOS equ H'B6' ; 10110110
TRES equ H'9E' ; 10011110
CUATRO equ H'CC' ; 11001100
CINCO equ H'DA' ; 11011010
SEIS equ H'FA' ; 11111010
SIETE equ H'0E' ; 00001110
OCHO equ H'FE' ; 11111110
NUEVE equ H'DE' ; 11011110
SEGM_OFF equ H'00' ; Todos los segmentos apagados. Separador entre horas
; y minutos apagado (RB0).

frac_sec equ H'0C' ; Fracciones de segundo (1/244)
segundos equ H'0D' ; Segundos
minutos equ H'0E' ; Minutos
horas equ H'0F' ; Horas
conta1 equ H'10' ; Variable 1 para bucle contador
;
display equ H'11' ; Indicador de display que debe actualizarse
digito1 equ H'12' ; Display unidad de minuto / unidad de segundo
digito2 equ H'13' ; Display decena de minuto / decena de segundo
digito3 equ H'14' ; Display unidad de hora
digito4 equ H'15' ; Display decena de hora
banderas equ H'16' ; Banderas; 3-CHG, 4-PSEG, 5-PMIN, 6-PHOR, 7-P_ON

;**************************************************************
ORG 0x00 ;Vector de Reset
goto INICIO
org 0x05 ;Salva el vector de interrupción
;**************************************************************

; SUBRUTINAS
;**************************************************************
CODIGO_7S ; Devuelve el código 7 segmentos
addwf PCL,F
retlw CERO
retlw UNO
retlw DOS
retlw TRES
retlw CUATRO
retlw CINCO
retlw SEIS
retlw SIETE
retlw OCHO
retlw NUEVE

;**************************************************************
; Comienzo del programa
;**************************************************************
;
INICIO
;  Configurar puertos como salidas, blanquear display
bsf STATUS,RP0 ; Activa el banco de memoria 1.
movlw B'10000011' ; Configuración del registro Option, RB Pull Up desconectadas
movwf OPTION_REG ; TMR0 en modo temporizador (uso de pulsos de reloj internos, Fosc/4)
; prescaler TMR0 a 1:16
movlw B'00000000'
movwf TRISA ; Pone todas las patillas del puerto A como salidas
movwf TRISB ; Pone todas las patillas del puerto B como salidas
bcf STATUS,RP0 ; Activa el banco de memoria 0.
;
; Establecer estados iniciales de las salidas
movlw DSPOFF
movwf PORTA ; Apaga los displays
movlw B'00000001' ; Todos los segmentos apagados. Separador
movwf PORTB ; entre horas y minutos encendido (RB0).
;
; Inicialización de variables:
movlw H'01'
movwf TMR0 ; Pone 01h en TMR0
movlw B'11111110'
movwf display ; Inicia display seleccionando decena de hora
movlw CERO
movwf digito1 ; Aparecerá un "0" en el display unidad de minutos
movwf digito2 ; Aparecerá un "0" en el display decena de minutos
movlw DOS
movwf digito3 ; Aparecerá un "2" en el display unidad de hora
movlw UNO
movwf digito4 ; Aparecerá un "1" en el display decena de hora
movlw B'00000000'
movwf banderas ; Coloca todas las banderas a 0
;
; Inicia las variables de tiempo
movlw FRAC_INI
movwf frac_sec ; 12
movlw SEGS_INI
movwf segundos ; 196
movlw MINS_INI
movwf minutos ; 196
movlw D'255'
movwf horas ; Las horas comienzan con 12 por lo que "horas" ha de ser 255
;
;**************************************************************
PRINCIPAL ; Rutina principal cíclica
;**************************************************************
;
;  Esperar al desbordamiento de TMR0
TMR0_LLENO
; 4 MHz -> 1 MHz
;   1.000.000 Hz / 16 = 62.500 Hz
;   62.500 Hz / 256 = 244,140625 Hz -> 4,096 ms
movf TMR0,W
btfss STATUS,Z ; TMR0 cuenta libremente para no perder ciclos del reloj
; escribiendo valores
goto TMR0_LLENO
;
; Se ha desbordado TMR0 y se han contado 256.
; Tarda en desbordarse 4.096 ciclos de reloj, 4,096 ms
incfsz frac_sec,F ; Se añade 1 a frac_sec
goto COMPROBAR_CHG ; Se comprueba el estado de “CHG” por si se ha activado
; algún pulsador o es necesario actualizar los valores
; de la hora que tienen que mostrarse en los displays
;
; Se ha desbordado frac_sec y se han contado 244 "frac_sec", 1 segundo.
; Tarda en desbordarse 4.096 ciclos de reloj, 4,096 ms * 244 = 999,424 ms
; Al no consegirse exactamente 1 segundo sino 0,999424 s, luego se necesitan ajustes
bsf PORTB,0 ; Se activa separador horas-minutos
movlw FRAC_INI
movwf frac_sec ; Restaura la variable frac_sec para la próxima vuelta
;
COMPROBAR_PUL ; Comprueba variables pulsadores
btfss banderas,P_ON ; Si no se ha pulsado nada, se pasa a INC_HORA
goto INC_HORA ; Incrementa segundos, minutos y horas. Ajustes y “CHG” a 1
btfsc banderas,PSEG ; Comprobar si se ha pulsado PSEG (Pulsador segundos)
goto INC_HORA ; Se ha pulsado PSEG, (Pul A) y se mostrarán
; los segundos en el display
;
PONER_RELOJ
movlw SEGS_INI ; 196d
movwf segundos ; Inicia los segundos cuando se pone el reloj en hora
;
PONER_MINUTOS
btfss banderas,PMIN ; Comprobar si se ha pulsado PMIN (Pulsador minutos)
goto PONER_HORAS ; No se ha pulsado PMIN, ir a comprobar estado de PHOR
movlw H'AF' ; 175d
movwf frac_sec     ; Avance rápido del tiempo cuando se ajustan minutos frac_sec = 175
incfsz minutos,F ; Incrementar los minutos
goto PONER_HORAS
movlw MINS_INI
movwf minutos ; Iniciar minutos si al incrementar se han desbordado
;
PONER_HORAS
btfss banderas,PHOR ; Comprobar si se ha pulsado PHOR (Pulsador horas)
goto OBTENER_H_M ; No se ha pulsado PHOR, no se cambian las horas
movlw H'7F' ; 127d
movwf frac_sec ; Avance rápido del tiempo cuando se ajustan horas frac_sec = 127
incfsz horas,F ; Incrementar la hora
goto OBTENER_H_M
movlw HORS_INI
movwf horas ; Iniciar la hora si al incrementar se han desbordado
goto OBTENER_H_M
;
INC_HORA ; Incrementar segundos, minutos y horas
; Ajustes cada minuto, hora y 12 horas
bsf banderas,CHG ; Se especifica que se ha producido un cambio
;
incfsz segundos,F ; Como ha pasado un segundo se incrementa "segundos"
goto COMPROBAR_CHG
movlw SEGS_INI   ; Se ha desbordado "segundos" y se reestablece el valor inicial
movwf segundos ; de "segundos" para la próxima vuelta
;
movlw ADJMIN ; Se resta 9 a "frac_sec" cada minuto para los ajustes de tiempo
subwf frac_sec,F ; El minuto será 9 "frac_sec" más largo
;
incfsz minutos,F   ; Se añade 1 minuto
goto COMPROBAR_CHG
movlw MINS_INI ; Se ha desbordado "minutos" y Se reestablece el valor inicial
movwf minutos   ; de "minutos" para la próxima vuelta
;
movlw ADJHOR ; Se suma 34 a "frac_sec" cada hora para los ajustes de tiempo
addwf frac_sec,F ; La hora será 34 "frac_sec" más corta
;
incfsz horas,F   ; Se añade 1 hora
goto COMPROBAR_CHG
movlw HORS_INI ; Se ha desbordado "horas" y se reestablece el valor inicial
movwf horas   ; de "horas" para la próxima vuelta
movlw ADJDIA ; Se resta 3 a "frac_sec" cada 12 horas para los ajustes de tiempo
subwf frac_sec,F ; Cada 12 horas se añadirán 3 "frac_sec"
;
; Se comprueba el estado de “CHG” por si se ha activado
; algún pulsador o es necesario actualizar los valores
; de la hora que tienen que mostrarse en los displays
; Se actualiza hora, displays y pulsadores cada 4,096 ms (244 veces por segundo)
COMPROBAR_CHG
btfss banderas,CHG ; Si no se han activado pulsadores ni ha cambiado la hora
  goto DISPLAY_PUL ; se salta a DISPLAY_PUL, que principalmente refresca uno de los
; displays cada vez que se accede a ella y escanea pulsadores.
;
COMPROBAR_SEG ;  Se comprueba si se activo el pulsador de segundos (Pul A)
; para mostrar los segundos en el display
btfss banderas,PSEG
goto OBTENER_H_M ; No estaba pulsado PSEG
movlw H'00' ; Se mostrarán los segundos en el display de minutos
movwf digito2 ; Variables "digito2" a 0
movwf digito3 ; Variables "digito3" a 0
movwf digito4 ; Variables "digito4" a 0
movlw SEGS_INI
subwf segundos,W
movwf digito1 ; Se guarda temporalmente el número de segundos en “digito1”
goto DIV_DIGITOS
;
OBTENER_H_M
movlw HORS_12H
subwf horas,W
movwf digito3 ; La variable digito3 almacena temporalmente el valor para las horas
movlw MINS_INI
subwf minutos,W
movwf digito1 ; La variable digito1 almacena temporalmente el valor para los minutos
;
DIV_DIGITOS ; Divide los segundos o los minutos y las horas en dígitos independientes
; ejemplo, [14] lo pasa a [1]-[4]
movlw H'00'
movwf digito4 ; Se ponen a cero las posiciones de las decenas
movwf digito2 ; para el caso de que no se incrementen
movlw H'02'
movwf conta1 ; Bucle para convertir cada número (segundos o minutos y horas)
movlw digito1 ; Dirección de digito1 en FSR para usar INDF
movwf FSR ; La primera vez, FSR = digito1 (minutos o segundos) y la segunda vez FSR = digito3 (horas)
goto LOOP
;
LOOP2 ; Este LOOP se utiliza para las horas después de trabajar con los minutos o los segundos
movlw digito3
movwf FSR
;
LOOP ; Este LOOP se utiliza primero para los minutos o los segundos y después para las horas
movlw D'10' ; Averiguar cuantas "decenas" hay en el número
subwf INDF,F ; En cada LOOP restar 10 al número
btfsc STATUS,C         ; Se comprueba "C", que se pone a 1 si en la resta no se ha
; producido llevada
goto INC_DECENAS   ; C = 1 por lo que se añade 1 a la posición de las decenas
addwf INDF,F ; C = 0, no se incrementan las decenas y se suma 10 para restaurar
; las unidades
goto PROX_NUM
;
INC_DECENAS
incf FSR,F ; El puntero apunta a la primera posición de las decenas
incf INDF,F ; Se añade 1 a las decenas
decf FSR,F   ; Se restaura el valor de INDF para apuntar al número
goto    LOOP ; para la próxima resta hasta que se termine
; Con "goto LOOP" se vuelve a comprobar si es necesario
; sumar uno a la decena cada vez que esta se ha incrementado
;
PROX_NUM ; Próximo número, primero ha sido segundos o minutos y luego horas
decfsz conta1,F
goto LOOP2
;
CONVER_COD_7S ; Convierte cada dígito a código 7 segmentos para los displays
movlw digito1
movwf FSR ; Coloca la dirección del primer digito (digito1) en FSR
movlw H'04'
movwf conta1 ; Prepara la variable conta1 para el bucle de los 4 displays
;
PROX_DIGITO
movf INDF,W ; Obtener el valor de la variable "digito" actual
call CODIGO_7S ; LLamar a la rutina de conversión a código 7 segmentos
movwf INDF ; Colocar en la variable "digito" el código 7 segmentos devuelto
incf FSR,F ; Incremente INDF para el próximo "digito"
decfsz conta1,F ; Permitir que conta1 de sólo 4 vueltas
goto PROX_DIGITO
;
;BORRAR_CERO ; Si hay un cero en el display de las decenas de hora
; no se muestra (borrado de los ceros a la izquierda)
; movlw CERO
; subwf digito4,W
; btfss STATUS,Z
; goto BORRAR_CERO_SEG
; movlw SEGM_OFF
; movwf digito4
;
BORRAR_CERO_SEG
btfss banderas,PSEG ; Si está pulsado PSEG no se muestra nada en el display de la
goto DISPLAY_PUL ; posición de la unidad de hora.
movlw SEGM_OFF ; Contando con BORRAR_CERO, esto significa que sólo se
movwf digito3 ; mostrarán los segundos.
movwf digito4
;
DISPLAY_PUL ; Se borran los bits de flag para actualizar su estado
; Escanea pulsadores, si alguno está pulsado se pone a 1
; el pulsador que le correspoda así como "P_ON" y "CHG"
; Muestra los dígitos correspondientes a los segundos o a
; los minutos y horas en el display que corresponda.
;
movlw B'00000000'
movwf banderas ; Se borran los bits de flag para actualizar su estado
;
; Apagar los displays
movlw DSPOFF
movwf PORTA
;
; Apagar los segmentos respetando separador horas-minutos
movlw SEGM_OFF ; Respeta valor RB0
xorwf PORTB, w
andlw B'11111110' ;  Poner "1" el la posición del bit a copiar
xorwf PORTB, f
;
; Configurar los bits 1, 2 y 3 de PORTB como entrada
bsf STATUS,RP0 ; Activa el banco 1.
movlw PULSADOR
movwf TRISB ; Se configuran los bits 1, 2 y 3 de PORTB como entrada
bcf STATUS,RP0 ; Activa el banco 0.
nop ; Las instrucciones "nop" pueden no ser necesarias.
nop ; En principio proporcionan el tiempo suficiente para que los
nop ; estados anteriores de las salidas se actualicen a través de
nop ; las resistencias de 10K (y de las de 820 ohm si está activado
nop ; algún pulsador) antes de leer las patillas del puerto.
;
COMPROBAR_PSEG ; Se comprueba Pulsador PSEG
btfss PORTB,1
goto COMPROBAR_PMIN
bsf banderas,CHG
bsf banderas,PSEG
bsf banderas,P_ON
;
COMPROBAR_PMIN ; Se comprueba Pulsador PMIN
btfss PORTB,2
goto COMPROBAR_PHOR
bsf banderas,CHG
bsf banderas,PMIN
bsf banderas,P_ON
;
COMPROBAR_PHOR ; Se comprueba Pulsador PHOR
btfss PORTB,3
goto ACTIVAR_SEGM
bsf banderas,CHG
bsf banderas,PHOR
bsf banderas,P_ON
;
ACTIVAR_SEGM ; Se coloca en PORTB el valor para los segmentos del display actual
bsf STATUS,RP0 ; Activa el banco 1.
movlw H'00'
movwf TRISB ; Puerto B como salida
bcf STATUS,RP0 ; Activa el banco 0.
;
; Se determina que display debe actualizarse, es decir, que dato debe
; presentarse en el puerto B y se establece el siguiente display
btfss display,0 ; Si es el primer display (decena de hora) tomar digito4
movf digito4,W
btfss display,1 ; Si es el segundo display (unidad de hora) tomar valor digito3
movf digito3,W
btfss display,2 ; Si es el tercer display (decena de min/seg) tomar valor digito2
movf digito2,W
btfss display,3 ; Si es el cuarto display (unidad de min/seg) tomar valor digito1
movf digito1,W
;
; Entregar el valor en puerto B y respetar valor RB0
xorwf PORTB, w
andlw B'11111110' ;  Poner "1" el la posición del bit a copiar
xorwf PORTB, f
;
btfsc frac_sec,7 ; Establecer el separador de horas y minutos a un 50%
bcf PORTB,0 ; del ciclo (1/2 segundo encendido, 1/2 segundo apagado)
;
movf display,W ; Tomar el valor del display que debe habilitarse
movwf PORTA ; Cada display se “enciende” con una cadencia de 244 Hz / 4 = 61 Hz  
; Cada display se “enciende” con una cadencia de 244 Hz / 4 = 61 Hz  
; En este momento están encendidos los segmentos correspondientes
;
rlf display,F ; Rota display 1 bit a la próxima posición
bsf display,0 ; Asegura un 1 en la posición más baja de display (luego se hará 0 si es necesario)
btfss display,4 ; Comprueba si el último display fue actualizado
bcf display,0 ; Si lo fue, se vuelve a habilitar el primer display
; La variable display va cambiando:
; 1111 1101
; 1111 1011
; 1111 0111
; 1110 1110
; 1101 1101
; 1011 1011
; 0111 0111
; 1110 1110
; Sólo valen los 4 bits menos significativos
;
goto    PRINCIPAL ; Volver a realizar todo el proceso
;
    END


Imagen que hice simulando en Proteus ISIS:


Ayudemos a toda la Cumunidad TODOPIC a compartir proyectos completos...
en especial con PICs de los mas Comunes y Faciles de usar y Conseguir como los PIC16F84A, PIC16F628A Lenguaje Ensamblador...

« Última modificación: 23 de Junio de 2013, 03:22:39 por guero_j25 »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Reloj Digital Como migrar un Codigo en Ensamblador del PIC16F84A al PIC16F628A
« Respuesta #1 en: 20 de Junio de 2013, 22:25:29 »
  No creo que haya mucho que modificar, ya que son pin a pin compatibles. En cuanto a la configuración del 628, tal vez necesites deshabilitar los comparadores. Puedes habilitar o no el MCLR. Deshabilitar LVP.

  Tienes que prestar atención a las direcciones de memoria de los distintos registros y ver que la memoria RAM sí empieza en una dirección diferente en 628 respecto al 84.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado Darkman_A

  • PIC18
  • ****
  • Mensajes: 288
Re: Reloj Digital Como migrar un Codigo en Ensamblador del PIC16F84A al PIC16F628A
« Respuesta #2 en: 20 de Junio de 2013, 22:39:20 »
Hola.
Fijate acá
Saludos

Desconectado guero_j25

  • PIC10
  • *
  • Mensajes: 3
Re: Reloj Digital Como migrar un Codigo en Ensamblador del PIC16F84A al PIC16F628A
« Respuesta #3 en: 20 de Junio de 2013, 23:42:38 »
Ok, gracias por sus aportaciones y sugerencias, intentare modificarlo y compilarlo en el MPLAB... Si alguien puede subir el programa ya modificado para el PIC16F628A se lo agradecere.

Tambien puedo compartir todo el proyecto totalmente funcional y totalmente documentado para el PIC16F84A incluyendo simulaciones etc. para quien lo desee con gusto lo comparto...

De paso les aviso que tambien estoy en proceso de creacion de la Tableta PCB, en cuanto la tenga lista tambien la compartire... yo pienso que solo asi podemos aprender y crecer, apoyandonos mutuamente.

Saludos y muchas gracias.  8)

Desconectado Darkman_A

  • PIC18
  • ****
  • Mensajes: 288
Re: Reloj Digital Como migrar un Codigo en Ensamblador del PIC16F84A al PIC16F628A
« Respuesta #4 en: 21 de Junio de 2013, 00:28:18 »
Ok, gracias por sus aportaciones y sugerencias, intentare modificarlo y compilarlo en el MPLAB... Si alguien puede subir el programa ya modificado para el PIC16F628A se lo agradecere.

Tambien puedo compartir todo el proyecto totalmente funcional y totalmente documentado para el PIC16F84A incluyendo simulaciones etc. para quien lo desee con gusto lo comparto...

De paso les aviso que tambien estoy en proceso de creacion de la Tableta PCB, en cuanto la tenga lista tambien la compartire... yo pienso que solo asi podemos aprender y crecer, apoyandonos mutuamente.

Saludos y muchas gracias.  8)

Hola.
¿El diseño del proyecto es tuyo?. Me refiero al circuito del reloj, la programacion, etc. en pic16f84a. Si no es tuya estaria bueno que nombraras la fuente.
Dado que lo estas ofreciendo, ¿Por que no lo subis y listo?. Quien quiera hacerlo solo tendria que descargarlo.
Con respecto a la migracion, no creo que se te complique.
Saludos.


Has sido el destinatario de mi mensaje Nº 100  :-)  :D
« Última modificación: 21 de Junio de 2013, 00:42:15 por Darkman_A »

Desconectado Virginia

  • PIC10
  • *
  • Mensajes: 2
Re:Reloj Digital Como migrar un Codigo en Ensamblador del PIC16F84A al PIC16F628A
« Respuesta #5 en: 18 de Junio de 2016, 12:08:44 »
EStoy tratando de migrar del pic16F84a a pic16F628a y no puedo :( me ayudan?
EL codigo es este:

;*************************************************************
; RELOJ DE 12 HORAS
;*************************************************************

          LIST P=PIC16F628A               ;Procesador utilizado.
#INCLUDE <P16F628A.INC>          ; Lista de etiquetas de microchip

      __CONFIG _LVP_OFF & _MCLRE_OFF & _BODEN_OFF & _CP_OFF & _PWRTE_ON & _WDT_ON & _INTOSC_OSC_NOCLKOUT

W       EQU 0
F       EQU 1
Z       EQU 3
PORTB   EQU 06
STATUS  EQU 03
INTCON  EQU 0BH
TMR0    EQU 01H
PCL     EQU 02H
FRAC_INI   equ      D'12'   ; Constante para inicio cuenta de fracciones de segundo
SEGS_INI   equ      D'196'   ; Constante para inicio cuenta de segundos
MINS_INI   equ      D'196'   ; Constante para inicio cuenta de minutos
HORS_INI   equ      D'244'   ; Constante para cuenta de horas
HORS_12H   equ      D'243'   ; Constante para cuenta de horas

ADJMIN      equ   D'9'      ; Número de "frac_sec" que se necesita sumar cada minuto
                       ; para ajustar el tiempo
ADJHOR      equ   D'34'      ; Número de "frac_sec" que se necesita restar cada hora
                       ; para ajustar el tiempo
ADJDIA      equ   D'3'      ; Número de "frac_sec" que se necesita sumar cada 12 horas
                       ; para ajustar el tiempo

; Activación de RB1-3 para las entradas de los pulsadores
PULSADOR   equ   B'00001110'   ; RB1, RB2 y RB3

; Asignación de banderas. Los pulsadores activos proporcionan un "1"
CHG      equ   H'03'          ; Indica que se ha activado un pulsador o que es necesario
                       ; actualizar los valores de la hora que tienen que mostrarse
                       ; en los displays
PSEG      equ   H'04'      ; Pulsador A, modo segundero.
PMIN      equ   H'05'      ; Pulsador B, avance rápido minutos.
PHOR      equ   H'06'      ; Pulsador C, avance rápido horas.
P_ON      equ   H'07'      ; Un pulsador ha sido activado

DSPOFF      equ   B'11111111'       ; Displays apagados (PORTA) gfedcbap
CERO      equ   B'01111110'     ; 01111110
UNO         equ   B'00001100'      ; 00001100
DOS         equ   B'10110110'      ; 10110110
TRES      equ   B'10011110'      ; 10011110
CUATRO      equ   B'11001100'      ; 11001100
CINCO      equ   B'11011010'      ; 11011010
SEIS      equ   B'11111010'      ; 11111010
SIETE      equ   B'00001110'      ; 00001110
OCHO      equ   B'11111110'      ;11111110
NUEVE      equ   B'11011110'      ; 11011110
SEGM_OFF   equ   H'00'      ; Todos los segmentos apagados. Separador entre horas y minutos apagado (RB0).
frac_sec   equ   H'0C'      ; Fracciones de segundo (1/244)
segundos   equ   H'0D'      ; Segundos
minutos      equ   H'0E'      ; Minutos
horas      equ   H'0F'      ; Horas
conta1      equ   H'10'      ; Variable 1 para bucle contador
display      equ   H'11'      ; Indicador de display que debe actualizarse
digito1      equ   H'12'      ; Display unidad de minuto / unidad de segundo
digito2      equ   H'13'      ; Display decena de minuto / decena de segundo
digito3      equ   H'14'      ; Display unidad de hora
digito4      equ   H'15'      ; Display decena de hora
banderas   equ   H'16'      ; Banderas; 3-CHG, 4-PSEG, 5-PMIN, 6-PHOR, 7-P_ON

;**************************************************************
    ORG   0x00         ;Vector de Reset
   goto   INICIO
   org   0x05      ;Salva el vector de interrupción
;**************************************************************

; SUBRUTINAS
;**************************************************************
CODIGO_7S            ; Devuelve el código 7 segmentos
   addwf   PCL,F
   retlw   CERO
   retlw   UNO
   retlw   DOS
   retlw   TRES
   retlw   CUATRO
   retlw   CINCO
   retlw   SEIS
   retlw   SIETE
   retlw   OCHO
   retlw   NUEVE

;**************************************************************
; Comienzo del programa
;**************************************************************
;
INICIO
;  Configurar puertos como salidas, blanquear display
   bsf   STATUS,RP0              ; Activa el banco de memoria 1.
    clrf   TRISB            ; Las líneas del Puerto B se configuran como salida.
   movlw   B'00000111'          ; Configuración del registro Option, RB Pull Up desconectadas
   movwf   OPTION_REG          ; TMR0 en modo temporizador (uso de pulsos de reloj internos, Fosc/4)
                           ; prescaler TMR0 a 1:16
   bcf   STATUS,RP0              ; Activa el banco de memoria 0.
    clrf   PORTB
;
; Establecer estados iniciales de las salidas
   movlw   DSPOFF
   movwf   PORTA         ; Apaga los displays
   movlw   B'00000001'      ; Todos los segmentos apagados. Separador
   movwf   PORTB         ; entre horas y minutos encendido (RB0).
;
; Inicialización de variables:
   movlw   H'01'
   movwf   TMR0         ; Pone 01h en TMR0
   movlw   B'11111110'
   movwf   display         ; Inicia display seleccionando decena de hora
   movlw   CERO
   movwf   digito1         ; Aparecerá un "0" en el display unidad de minutos
   movwf   digito2         ; Aparecerá un "0" en el display decena de minutos
   movlw   DOS
   movwf   digito3         ; Aparecerá un "2" en el display unidad de hora
   movlw   UNO
   movwf   digito4         ; Aparecerá un "1" en el display decena de hora
   movlw   B'00000000'
   movwf   banderas      ; Coloca todas las banderas a 0
;
; Inicia las variables de tiempo
   movlw   FRAC_INI
   movwf   frac_sec      ; 12
   movlw   SEGS_INI
   movwf   segundos      ; 196
   movlw   MINS_INI
   movwf   minutos         ; 196
   movlw   D'255'
   movwf   horas         ; Las horas comienzan con 12 por lo que "horas" ha de ser 255
;
;**************************************************************
PRINCIPAL ; Rutina principal cíclica
;**************************************************************
;
;  Esperar al desbordamiento de TMR0
TMR0_LLENO
;   4 MHz -> 1 MHz
;   1.000.000 Hz / 16 = 62.500 Hz
;   62.500 Hz / 256 = 244,140625 Hz -> 4,096 ms
   movf   TMR0,W
   btfss   STATUS,Z      ; TMR0 cuenta libremente para no perder ciclos del reloj
               ; escribiendo valores
   goto   TMR0_LLENO
;
; Se ha desbordado TMR0 y se han contado 256.
; Tarda en desbordarse 4.096 ciclos de reloj, 4,096 ms
   incfsz   frac_sec,F      ; Se añade 1 a frac_sec
   goto   COMPROBAR_CHG      ; Se comprueba el estado de ?CHG? por si se ha activado
               ; algún pulsador o es necesario actualizar los valores
               ; de la hora que tienen que mostrarse en los displays
;
; Se ha desbordado frac_sec y se han contado 244 "frac_sec", 1 segundo.
; Tarda en desbordarse 4.096 ciclos de reloj, 4,096 ms * 244 = 999,424 ms
; Al no consegirse exactamente 1 segundo sino 0,999424 s, luego se necesitan ajustes
   bsf   PORTB,0         ; Se activa separador horas-minutos
   movlw   FRAC_INI
   movwf   frac_sec      ; Restaura la variable frac_sec para la próxima vuelta
;
COMPROBAR_PUL   ; Comprueba variables pulsadores
   btfss   banderas,P_ON      ; Si no se ha pulsado nada, se pasa a INC_HORA
   goto   INC_HORA      ; Incrementa segundos, minutos y horas. Ajustes y ?CHG? a 1
   btfsc   banderas,PSEG      ; Comprobar si se ha pulsado PSEG (Pulsador segundos)
   goto   INC_HORA      ; Se ha pulsado PSEG, (Pul A) y se mostrarán
               ; los segundos en el display
;
PONER_RELOJ
   movlw   SEGS_INI      ; 196d
   movwf   segundos      ; Inicia los segundos cuando se pone el reloj en hora
;
PONER_MINUTOS
   btfss   banderas,PMIN      ; Comprobar si se ha pulsado PMIN (Pulsador minutos)
   goto   PONER_HORAS      ; No se ha pulsado PMIN, ir a comprobar estado de PHOR
   movlw   H'AF'         ; 175d
   movwf   frac_sec          ; Avance rápido del tiempo cuando se ajustan minutos frac_sec = 175
   incfsz   minutos,F      ; Incrementar los minutos
   goto   PONER_HORAS
   movlw   MINS_INI
   movwf   minutos         ; Iniciar minutos si al incrementar se han desbordado
;
PONER_HORAS
   btfss   banderas,PHOR      ; Comprobar si se ha pulsado PHOR (Pulsador horas)
   goto   OBTENER_H_M      ; No se ha pulsado PHOR, no se cambian las horas
   movlw   H'7F'         ; 127d
   movwf   frac_sec      ; Avance rápido del tiempo cuando se ajustan horas frac_sec = 127
   incfsz   horas,F         ; Incrementar la hora
   goto   OBTENER_H_M
   movlw   HORS_INI
   movwf   horas         ; Iniciar la hora si al incrementar se han desbordado
   goto   OBTENER_H_M
;
INC_HORA            ; Incrementar segundos, minutos y horas
               ; Ajustes cada minuto, hora y 12 horas
   bsf   banderas,CHG      ; Se especifica que se ha producido un cambio
;
   incfsz   segundos,F       ; Como ha pasado un segundo se incrementa "segundos"
   goto   COMPROBAR_CHG
   movlw   SEGS_INI         ; Se ha desbordado "segundos" y se reestablece el valor inicial
   movwf   segundos      ; de "segundos" para la próxima vuelta
;
   movlw   ADJMIN         ; Se resta 9 a "frac_sec" cada minuto para los ajustes de tiempo
   subwf   frac_sec,F       ; El minuto será 9 "frac_sec" más largo
;
   incfsz   minutos,F        ; Se añade 1 minuto
   goto   COMPROBAR_CHG
   movlw   MINS_INI      ; Se ha desbordado "minutos" y Se reestablece el valor inicial
   movwf   minutos           ; de "minutos" para la próxima vuelta
;
   movlw   ADJHOR         ; Se suma 34 a "frac_sec" cada hora para los ajustes de tiempo
   addwf   frac_sec,F      ; La hora será 34 "frac_sec" más corta
;
   incfsz   horas,F           ; Se añade 1 hora
   goto   COMPROBAR_CHG
   movlw   HORS_INI      ; Se ha desbordado "horas" y se reestablece el valor inicial
   movwf   horas           ; de "horas" para la próxima vuelta
   movlw   ADJDIA         ; Se resta 3 a "frac_sec" cada 12 horas para los ajustes de tiempo
   subwf   frac_sec,F       ; Cada 12 horas se añadirán 3 "frac_sec"
;
; Se comprueba el estado de ?CHG? por si se ha activado
; algún pulsador o es necesario actualizar los valores
; de la hora que tienen que mostrarse en los displays
; Se actualiza hora, displays y pulsadores cada 4,096 ms (244 veces por segundo)
COMPROBAR_CHG
   btfss   banderas,CHG      ; Si no se han activado pulsadores ni ha cambiado la hora
    goto   DISPLAY_PUL      ; se salta a DISPLAY_PUL, que principalmente refresca uno de los
               ; displays cada vez que se accede a ella y escanea pulsadores.
;
COMPROBAR_SEG            ;  Se comprueba si se activo el pulsador de segundos (Pul A)
               ; para mostrar los segundos en el display
   btfss   banderas,PSEG
   goto   OBTENER_H_M      ; No estaba pulsado PSEG
   movlw   H'00'         ; Se mostrarán los segundos en el display de minutos
   movwf   digito2         ; Variables "digito2" a 0
   movwf   digito3         ; Variables "digito3" a 0
   movwf   digito4         ; Variables "digito4" a 0
   movlw   SEGS_INI
   subwf   segundos,W
   movwf   digito1         ; Se guarda temporalmente el número de segundos en ?digito1?
   goto   DIV_DIGITOS
;
OBTENER_H_M
   movlw   HORS_12H
   subwf   horas,W
   movwf   digito3         ; La variable digito3 almacena temporalmente el valor para las horas
   movlw   MINS_INI
   subwf   minutos,W
   movwf   digito1         ; La variable digito1 almacena temporalmente el valor para los minutos
;
DIV_DIGITOS            ; Divide los segundos o los minutos y las horas en dígitos independientes
               ; ejemplo, [14] lo pasa a [1]-[4]
   movlw   H'00'
   movwf   digito4         ; Se ponen a cero las posiciones de las decenas
   movwf   digito2         ; para el caso de que no se incrementen
   movlw   H'02'
   movwf   conta1         ; Bucle para convertir cada número (segundos o minutos y horas)
   movlw   digito1         ; Dirección de digito1 en FSR para usar INDF
   movwf   FSR         ; La primera vez, FSR = digito1 (minutos o segundos) y la segunda vez FSR = digito3 (horas)
   goto   LOOP
;
LOOP2   ; Este LOOP se utiliza para las horas después de trabajar con los minutos o los segundos
   movlw   digito3
   movwf   FSR
;
LOOP   ; Este LOOP se utiliza primero para los minutos o los segundos y después para las horas
   movlw   D'10'         ; Averiguar cuantas "decenas" hay en el número
   subwf   INDF,F         ; En cada LOOP restar 10 al número
   btfsc   STATUS,C           ; Se comprueba "C", que se pone a 1 si en la resta no se ha
               ; producido llevada
   goto   INC_DECENAS         ; C = 1 por lo que se añade 1 a la posición de las decenas
   addwf   INDF,F         ; C = 0, no se incrementan las decenas y se suma 10 para restaurar
               ; las unidades
   goto   PROX_NUM
;
INC_DECENAS
   incf   FSR,F         ; El puntero apunta a la primera posición de las decenas
   incf   INDF,F         ; Se añade 1 a las decenas
   decf   FSR,F           ; Se restaura el valor de INDF para apuntar al número
   goto    LOOP         ; para la próxima resta hasta que se termine
               ; Con "goto LOOP" se vuelve a comprobar si es necesario
               ; sumar uno a la decena cada vez que esta se ha incrementado
;
PROX_NUM            ; Próximo número, primero ha sido segundos o minutos y luego horas
   decfsz   conta1,F
   goto   LOOP2
;
CONVER_COD_7S            ; Convierte cada dígito a código 7 segmentos para los displays
   movlw   digito1
   movwf   FSR         ; Coloca la dirección del primer digito (digito1) en FSR
   movlw   H'04'
   movwf   conta1         ; Prepara la variable conta1 para el bucle de los 4 displays
;
PROX_DIGITO
   movf   INDF,W         ; Obtener el valor de la variable "digito" actual
   call   CODIGO_7S      ; LLamar a la rutina de conversión a código 7 segmentos
   movwf   INDF         ; Colocar en la variable "digito" el código 7 segmentos devuelto
   incf   FSR,F         ; Incremente INDF para el próximo "digito"
   decfsz   conta1,F      ; Permitir que conta1 de sólo 4 vueltas
   goto   PROX_DIGITO
;
;BORRAR_CERO            ; Si hay un cero en el display de las decenas de hora
               ; no se muestra (borrado de los ceros a la izquierda)
;   movlw   CERO
;   subwf   digito4,W
;   btfss   STATUS,Z
;   goto   BORRAR_CERO_SEG
;   movlw   SEGM_OFF
;   movwf   digito4
;
BORRAR_CERO_SEG
   btfss   banderas,PSEG      ; Si está pulsado PSEG no se muestra nada en el display de la
   goto   DISPLAY_PUL      ; posición de la unidad de hora.
   movlw   SEGM_OFF      ; Contando con BORRAR_CERO, esto significa que sólo se
   movwf   digito3         ; mostrarán los segundos.
   movwf   digito4
;
DISPLAY_PUL            ; Se borran los bits de flag para actualizar su estado
               ; Escanea pulsadores, si alguno está pulsado se pone a 1
               ; el pulsador que le correspoda así como "P_ON" y "CHG"
               ; Muestra los dígitos correspondientes a los segundos o a
               ; los minutos y horas en el display que corresponda.
;
   movlw   B'00000000'
   movwf   banderas      ; Se borran los bits de flag para actualizar su estado
;
   ; Apagar los displays
   movlw   DSPOFF
   movwf   PORTA
;
   ; Apagar los segmentos respetando separador horas-minutos
   movlw   SEGM_OFF      ; Respeta valor RB0
   xorwf   PORTB, w
   andlw   B'11111110'      ;  Poner "1" el la posición del bit a copiar
   xorwf   PORTB, f
;
   ; Configurar los bits 1, 2 y 3 de PORTB como entrada
   bsf   STATUS,RP0      ; Activa el banco 1.
   movlw   PULSADOR
   movwf   TRISB         ; Se configuran los bits 1, 2 y 3 de PORTB como entrada
   bcf   STATUS,RP0      ; Activa el banco 0.
   nop            ; Las instrucciones "nop" pueden no ser necesarias.
   nop            ; En principio proporcionan el tiempo suficiente para que los
   nop            ; estados anteriores de las salidas se actualicen a través de
   nop            ; las resistencias de 10K (y de las de 820 ohm si está activado
   nop            ; algún pulsador) antes de leer las patillas del puerto.
;
COMPROBAR_PSEG   ; Se comprueba Pulsador PSEG
   btfss   PORTB,1
   goto   COMPROBAR_PMIN
   bsf   banderas,CHG
   bsf   banderas,PSEG
   bsf   banderas,P_ON
;
COMPROBAR_PMIN   ; Se comprueba Pulsador PMIN
   btfss   PORTB,2
   goto   COMPROBAR_PHOR
   bsf   banderas,CHG
   bsf   banderas,PMIN
   bsf   banderas,P_ON
;
COMPROBAR_PHOR   ; Se comprueba Pulsador PHOR
   btfss   PORTB,3
   goto   ACTIVAR_SEGM
   bsf   banderas,CHG
   bsf   banderas,PHOR
   bsf   banderas,P_ON
;
ACTIVAR_SEGM   ; Se coloca en PORTB el valor para los segmentos del display actual
   bsf   STATUS,RP0      ; Activa el banco 1.
   movlw   H'00'
   movwf   TRISB         ; Puerto B como salida
   bcf   STATUS,RP0      ; Activa el banco 0.
;
   ; Se determina que display debe actualizarse, es decir, que dato debe
   ; presentarse en el puerto B y se establece el siguiente display
   btfss   display,0      ; Si es el primer display (decena de hora) tomar digito4
   movf   digito4,W
   btfss   display,1      ; Si es el segundo display (unidad de hora) tomar valor digito3
   movf   digito3,W
   btfss   display,2      ; Si es el tercer display (decena de min/seg) tomar valor digito2
   movf   digito2,W
   btfss   display,3      ; Si es el cuarto display (unidad de min/seg) tomar valor digito1
   movf   digito1,W
;
   ; Entregar el valor en puerto B y respetar valor RB0
   xorwf   PORTB, w
   andlw   B'11111110'      ;  Poner "1" el la posición del bit a copiar
   xorwf   PORTB, f
;
   btfsc   frac_sec,7      ; Establecer el separador de horas y minutos a un 50%
   bcf   PORTB,0         ; del ciclo (1/2 segundo encendido, 1/2 segundo apagado)
;
   movf   display,W      ; Tomar el valor del display que debe habilitarse
   movwf   PORTA         ; Cada display se ?enciende? con una cadencia de 244 Hz / 4 = 61 Hz
   ; Cada display se ?enciende? con una cadencia de 244 Hz / 4 = 61 Hz
   ; En este momento están encendidos los segmentos correspondientes
;
   rlf   display,F      ; Rota display 1 bit a la próxima posición
   bsf   display,0      ; Asegura un 1 en la posición más baja de display (luego se hará 0 si es necesario)
   btfss   display,4      ; Comprueba si el último display fue actualizado
   bcf   display,0      ; Si lo fue, se vuelve a habilitar el primer display
               ; La variable display va cambiando:
               ;   1111 1101
               ;   1111 1011
               ;   1111 0111
               ;   1110 1110
               ;   1101 1101
               ;   1011 1011
               ;   0111 0111
               ;   1110 1110
               ; Sólo valen los 4 bits menos significativos
;
   goto    PRINCIPAL      ; Volver a realizar todo el proceso
;
    END

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Reloj Digital Como migrar un Codigo en Ensamblador del PIC16F84A al PIC16F628A
« Respuesta #6 en: 18 de Junio de 2016, 16:37:35 »
Por favor no repitas los mensajes, va en contra de las reglas del foro, ahi te conteste en tu otro tema que creaste:

http://www.todopic.com.ar/foros/index.php?topic=46455.new#new

Desconectado elreypic2

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1297
Re:Reloj Digital Como migrar un Codigo en Ensamblador del PIC16F84A al PIC16F628A
« Respuesta #7 en: 01 de Noviembre de 2016, 01:17:20 »
Aquí les dejo la conversión para un PIC16F627A usando displays de 7 segmentos de cátodo común.

Código: ASM
  1. ;*************************************************************
  2. ; RELOJ DE 12 HORAS
  3. ;*************************************************************
  4. ;
  5. ; Programa original:    CLOCK54.ASM
  6. ;                                               Dan Matthews
  7. ;                                               Microchip Technology Inc.
  8. ;                                               16 de enero de 1997
  9. ;                                               www.microchip.com, AN590.PDF
  10. ; Revisión:                            RELOJ12H.ASM
  11. ;                                               Emilio Toboso
  12. ;                                               I.E.S. "La Fuensanta" Córdoba
  13. ;                                               Abril de 2005
  14. ; Programa para PIC16F84A
  15. ; Frecuencia de reloj: 4 MHz
  16. ; Instrucción: 1Mz = 1 us
  17. ; Perro Guardián: OFF
  18. ; Tipo de Reloj: XT
  19. ; Protección de código: OFF
  20. ; POR: ON
  21. ;
  22. ; Revisión:                            reloj12hccA_F627.ASM
  23. ;                                               Miguel Angel Meza CAmpos
  24. ;                                               Wylie, TX 75098
  25. ;                                               Octubre 31 del 2016
  26. ; Programa para PIC16F627A
  27. ; Frecuencia de reloj: 4MHz
  28. ; Ciclo instrucción: 1MHz = 1 us
  29. ; WDT ("Perro guardián"): OFF
  30. ; Tipo de Reloj: INTOSC
  31. ; Protección de código: ON
  32. ; Power-On Reset: ON
  33. ; MCLR: Deshabilitado
  34. ; BODEN: Habilitado
  35. ; Protección de datos: OFF
  36. ;
  37. ;*************************************************************
  38. ; DESCRIPCIÓN DEL PROGRAMA
  39. ;*************************************************************
  40. ;
  41. ; Este programa funciona en un PIC16F84A y se trata de un reloj
  42. ; de 12 horas que muestra horas y minutos.
  43. ; Dispone de dos displays LED para las horas y otros dos para los
  44. ; minutos.
  45. ; Para programar la hora se dispone de un pulsador de avance rápido
  46. ; de horas y de otro para avance rápido de minutos.
  47. ; También se dispone de un tercer pulsador que se utiliza para mostrar
  48. ; los segundos mientras permanezca pulsado.
  49. ;  
  50. ; DESCRIPCIÓN DEL HARDWARE
  51. ;  
  52. ; VISUALIZACIÓN:  
  53. ;
  54. ; La hora se muestra mediante cuatro displays de 7 segmentos de cátodo
  55. ; común multiplexados. Los segmentos de cada display se unen y estan
  56. ; controlados a través de resistencias por salidas del PIC. Cada cátodo
  57. ; común de cada display es controlado por el PIC a través de un transistor.
  58. ; El reloj presenta las horas y minutos por dos puntos (88:88). Los
  59. ; segmentos se asignan al puerto B.
  60. ; Los dos puntos se realizan mediante dos LED en serie con una resistencia
  61. ; y se conectan a RB0.
  62. ; Los segmentos de los displays, de "a" hasta "f" se asignan a las salidas
  63. ; de RB1 a RB7.  
  64. ; Los cuatro cátodos comunes se controlan mediante el puerto A a través de
  65. ; los transistores.  
  66. ; RA0 controla la decena de hora, RA1 la unidad de hora; RA2 la decena de
  67. ; minuto y RA3 la unidad de minuto.  
  68. ;  
  69. ; PULSADORES:  
  70. ;
  71. ; Sobre los tres pulsadores:
  72. ; Pulsador avance rápido de horas conectado a RB3
  73. ; Pulsador avance rápido de minutos conectado a RB2
  74. ; Pulsador para mostrar los segundos conectado a RB1
  75. ;
  76. ; Debido a que todas las patillas E/S (salvo RA4) están utilizadas,  
  77. ; se debe comprobar el estado de los pulsadores estableciendo como salidas
  78. ; o como entradas alternativamente las patillas a las que están conectados.
  79. ; Los pulsadores utilizan el Puerto B que cambiará a entrada durante un
  80. ; instante para comprobar el estado de los pulsadores.  
  81. ;
  82. ;
  83. ;
  84. ;
  85. ;
  86. ;
  87. ;
  88. ;
  89. ;
  90. ;
  91. ;
  92. ;
  93. ;*************************************************************
  94. ; PATILLAS
  95. ;*************************************************************
  96. ;                                           ____________
  97. ; DISPLAY DECENA MIN / DECENA SEG -> RA,2 -|1   \__/  18|- RA,1 <- DISPLAY UNIDAD HR
  98. ; DISPLAY UNIDAD MIN / UNIDAD SEG -> RA,3 -|2         17|- RA,0 <- DISPLAY DECENA HR
  99. ;                                      NC -|3 16F627A 16|- NC          
  100. ;                                      NC -|4         15|- NC
  101. ;                                     GND -|5         14|- Vcc
  102. ;                        PUNTO dp -> RB,0 -|6         13|- RB,7 -> SEGMENTO g
  103. ;        PUL A (SEG) / SEGMENTO a -> RB,1 -|7         12|- RB,6 -> SEGMENTO f
  104. ;        PUL B (MIN) / SEGMENTO b -> RB,2 -|8         11|- RB,5 -> SEGMENTO e
  105. ;        PUL C (HOR) / SEGMENTO c -> RB,3 -|9_________10|- RB,4 -> SEGMENTO d      
  106. ;
  107. ; PORTA, control displays 7 segmentos de cátodo común
  108. ; PORTB, segmetos de los displays, led separadores, pulsadores como entrada
  109. ;
  110. ; El pulsador A (conectado a RB1) muestra el segundero en tanto permanezca presionado.
  111. ; El pulsador B (conectado a RB2) avanza rápidamente los minutos.
  112. ; El pulsador C (conectado a RB3) avanza rápidamente las horas.
  113. ;
  114. ;*************************************************************
  115.         LIST P=PIC16F627A               ; Pic a usar
  116. #INCLUDE <P16F627A.INC>         ; Lista de etiquetas de microchip
  117. ;
  118. ;*************************************************************
  119. ; Configuración opciones de hardware para la programación
  120.                 __CONFIG    _CP_ON & _PWRTE_ON & _WDT_OFF & _INTOSC_OSC_NOCLKOUT & _MCLRE_OFF & _BOREN_ON & _LVP_OFF & _CPD_OFF
  121. ;
  122. ;**************************************************************
  123. ; Lista de constantes y variables para el uso del programa
  124. ;**************************************************************
  125. ;
  126. ; Valores de constantes ***************************************
  127. ;
  128. FRAC_INI        equ             D'12'   ; Constante para inicio cuenta de fracciones de segundo
  129. SEGS_INI        equ             D'196'  ; Constante para inicio cuenta de segundos
  130. MINS_INI        equ             D'196'  ; Constante para inicio cuenta de minutos
  131. HORS_INI        equ             D'244'  ; Constante para cuenta de horas
  132. HORS_12H        equ             D'243'  ; Constante para cuenta de horas
  133. ; HORS_12H se utiliza para el cálculo de las horas a mostrar.
  134. ; Si nos encontramos a las 1:00 la variable "horas" será igual a HORS_INI (244) y el
  135. ; cálculo para mostrar la hora será:
  136. ; Hora display = horas - HORS_12H = 244 - 243 = 1
  137. ; Si son las doce, la variable "horas" será igual a 255 de manera que se mostrará:
  138. ; Hora display = horas - HORS_12H = 255 - 243 = 12
  139. ADJMIN          equ             D'9'    ; Número de "frac_sec" que se necesita sumar cada minuto
  140.                                                         ; para ajustar el tiempo
  141. ADJHOR          equ             D'34'   ; Número de "frac_sec" que se necesita restar cada hora
  142.                                                         ; para ajustar el tiempo
  143. ADJDIA          equ             D'3'    ; Número de "frac_sec" que se necesita sumar cada 12 horas
  144.                                                         ; para ajustar el tiempo
  145. ;Ajustes
  146. ; Un "frac_sec" es aproximadamente 1 / 244 s
  147. ; 1 MHz / 16 = 62.500 Hz ; 62.500 Hz / 256 = 244,140625 Hz ; T = 0,004096 s
  148. ; 0,004096 s * 244 = 0,999424 s; dif 1 segundo = -0,000576 s
  149. ; 1 "minuto" = 0,999424 s * 60 = 59,96544 s
  150. ; 60 s - 59,96544 s = 0,03456 s ; 0,03456 s / 0,004096 s = 8,4375
  151. ; 1 "minutoadj" = 59,96544 s + (0,004096 s * 9) = 59,96544 s + 0,036864 s = 60,002304 s
  152. ; 1 "hora" = 60,002304 s * 60 = 3600,13824 s
  153. ; 3600 s - 3600,13824 s = -0,13824 s ; -0,13824 s / 0,004096 s = -33,75 s
  154. ; 1 "horaadj" = 3600,13824 s - (0,004096 s * 34) = 3600,13824 s - 0,139264 s = 3599,998976 s
  155. ; 12 "horas" = 3599,998976 s * 12 = 43199,987712 s
  156. ; 43200 s - 43199,987712 s = 0,012288 s ; 0,012288 s /  0,004096 s = 3
  157. ; 12 "horasadj" = 43199,987712 s + 0,004096 s * 3 = 43199,987712 s + 0,012288 s = 43200 s
  158. ;
  159. ; Activación de RB1-3 para las entradas de los pulsadores
  160. PULSADOR        equ             B'00001110'     ; RB1, RB2 y RB3
  161. ;
  162. ; Asignación de banderas. Los pulsadores activos proporcionan un "1"
  163. CHG                     equ             H'03'   ; Indica que se ha activado un pulsador o que es necesario
  164.                                                         ; actualizar los valores de la hora que tienen que mostrarse
  165.                                                         ; en los displays
  166. PSEG            equ             H'04'   ; Pulsador A, modo segundero.
  167. PMIN            equ             H'05'   ; Pulsador B, avance rápido minutos.
  168. PHOR            equ             H'06'   ; Pulsador C, avance rápido horas.
  169. P_ON            equ             H'07'   ; Un pulsador ha sido activado
  170. ;
  171. DSPOFF          equ             B'00000000'     ; Displays apagados (PORTA)
  172. ;
  173. ; Mapa de activación de segmentos para los displays (PORTB)
  174. ;         a
  175. ;         =========
  176. ;         |       |
  177. ;       f |       | b
  178. ;         |   g   |
  179. ;         =========
  180. ;         |       |
  181. ;       e |       | c
  182. ;         |       |
  183. ;         ========= # p
  184. ;         d
  185. ;
  186.                                                         ; gfedcbap
  187. CERO            equ             H'7E'   ; 01111110
  188. UNO                     equ             H'0C'   ; 00001100
  189. DOS                     equ             H'B6'   ; 10110110
  190. TRES            equ             H'9E'   ; 10011110
  191. CUATRO          equ             H'CC'   ; 11001100
  192. CINCO           equ             H'DA'   ; 11011010
  193. SEIS            equ             H'FA'   ; 11111010
  194. SIETE           equ             H'0E'   ; 00001110
  195. OCHO            equ             H'FE'   ; 11111110
  196. NUEVE           equ             H'DE'   ; 11011110
  197. SEGM_OFF        equ             H'00'   ; Todos los segmentos apagados. Separador entre horas
  198.                                                         ; y minutos apagado (RB0).
  199. ;
  200. ; Posición de memoria de variables ************************************
  201. ; Las variables de tiempo comienzan con un número que permite contar y ajustar el tiempo  
  202. ; Por ejemplo la variable "segundos" se inicia con 196 decimal, para que después de 60
  203. ; incrementos de 1 segundo se produzca un 0 (196 + 60 = 256 -> 0)
  204. frac_sec        equ             H'20'   ; Fracciones de segundo (1/244)
  205. segundos        equ             H'21'   ; Segundos
  206. minutos         equ             H'22'   ; Minutos
  207. horas           equ             H'23'   ; Horas
  208. conta1          equ             H'24'   ; Variable 1 para bucle contador
  209. ;
  210. display         equ     H'25'   ; Indicador de display que debe actualizarse
  211. digito1         equ             H'26'   ; Display unidad de minuto / unidad de segundo
  212. digito2         equ             H'27'   ; Display decena de minuto / decena de segundo
  213. digito3         equ             H'28'   ; Display unidad de hora
  214. digito4         equ             H'29'   ; Display decena de hora
  215. banderas        equ     H'2A'   ; Banderas; 3-CHG, 4-PSEG, 5-PMIN, 6-PHOR, 7-P_ON
  216. ;
  217. ;**************************************************************
  218.         ORG 0x00                ;Vector de Reset
  219.         goto    INICIO
  220. ;**************************************************************
  221. ; SUBRUTINAS
  222. ;**************************************************************
  223. CODIGO_7S       ; Devuelve el código 7 segmentos
  224.         addwf   PCL,F
  225.         retlw   CERO
  226.         retlw   UNO
  227.         retlw   DOS
  228.         retlw   TRES
  229.         retlw   CUATRO
  230.         retlw   CINCO
  231.         retlw   SEIS
  232.         retlw   SIETE
  233.         retlw   OCHO
  234.         retlw   NUEVE
  235. ;**************************************************************
  236.  
  237. ;**************************************************************
  238. ; Comienzo del programa
  239. ;**************************************************************
  240. ;
  241. INICIO
  242. ;  Configurar puertos como salidas, blanquear display
  243.         movlw   .7                     
  244.         movwf   CMCON           ;Configura puerto A como digital
  245.         bsf             STATUS,RP0      ; Activa el banco de memoria 1.
  246.         movlw   B'10000011' ; Configuración del registro Option, RB Pull Up desconectadas
  247.         movwf   OPTION_REG      ; TMR0 en modo temporizador (uso de pulsos de reloj internos, Fosc/4)
  248.                                                 ; prescaler TMR0 a 1:16
  249.         movlw   B'00000000'
  250.         movwf   TRISA           ; Pone todas las patillas del puerto A como salidas
  251.         movwf   TRISB           ; Pone todas las patillas del puerto B como salidas
  252.         bcf             STATUS,RP0      ; Activa el banco de memoria 0.
  253. ;
  254. ; Establecer estados iniciales de las salidas
  255.         movlw   DSPOFF
  256.         movwf   PORTA           ; Apaga los displays
  257.         movlw   B'00000001'     ; Todos los segmentos apagados. Separador
  258.         movwf   PORTB           ; entre horas y minutos encendido (RB0).
  259. ;
  260. ; Inicialización de variables:
  261.         movlw   H'01'
  262.         movwf   TMR0            ; Pone 01h en TMR0
  263.         movlw   B'11111110'    
  264.         movwf   display         ; Inicia display seleccionando decena de hora
  265.         movlw   CERO
  266.         movwf   digito1         ; Aparecerá un "0" en el display unidad de minutos
  267.         movwf   digito2         ; Aparecerá un "0" en el display decena de minutos
  268.         movlw   DOS
  269.         movwf   digito3         ; Aparecerá un "2" en el display unidad de hora
  270.         movlw   UNO
  271.         movwf   digito4         ; Aparecerá un "1" en el display decena de hora
  272.         movlw   B'00000000'
  273.         movwf   banderas        ; Coloca todas las banderas a 0
  274. ;
  275. ; Inicia las variables de tiempo
  276.         movlw   FRAC_INI
  277.         movwf   frac_sec        ; 12
  278.         movlw   SEGS_INI
  279.         movwf   segundos        ; 196
  280.         movlw   MINS_INI
  281.         movwf   minutos         ; 196
  282.         movlw   D'255'
  283.         movwf   horas           ; Las horas comienzan con 12 por lo que "horas" ha de ser 255
  284. ;
  285. ;**************************************************************
  286. PRINCIPAL ; Rutina principal cíclica
  287. ;**************************************************************
  288. ;
  289. ;  Esperar al desbordamiento de TMR0
  290. TMR0_LLENO
  291. ;       4 MHz -> 1 MHz
  292. ;   1.000.000 Hz / 16 = 62.500 Hz
  293. ;   62.500 Hz / 256 = 244,140625 Hz -> 4,096 ms
  294.         movf    TMR0,W
  295.         btfss   STATUS,Z        ; TMR0 cuenta libremente para no perder ciclos del reloj
  296.                                                 ; escribiendo valores
  297.         goto    TMR0_LLENO
  298. ;
  299. ; Se ha desbordado TMR0 y se han contado 256.
  300. ; Tarda en desbordarse 4.096 ciclos de reloj, 4,096 ms
  301.         incfsz  frac_sec,F              ; Se añade 1 a frac_sec
  302.         goto    COMPROBAR_CHG   ; Se comprueba el estado de “CHG” por si se ha activado
  303.                                                         ; algún pulsador o es necesario actualizar los valores
  304.                                                         ; de la hora que tienen que mostrarse en los displays
  305. ;
  306. ; Se ha desbordado frac_sec y se han contado 244 "frac_sec", 1 segundo.
  307. ; Tarda en desbordarse 4.096 ciclos de reloj, 4,096 ms * 244 = 999,424 ms
  308. ; Al no consegirse exactamente 1 segundo sino 0,999424 s, luego se necesitan ajustes
  309.         bsf             PORTB,0         ; Se activa separador horas-minutos
  310.         movlw   FRAC_INI
  311.         movwf   frac_sec  ; Restaura la variable frac_sec para la próxima vuelta
  312. ;
  313. COMPROBAR_PUL   ; Comprueba variables pulsadores
  314.         btfss   banderas,P_ON   ; Si no se ha pulsado nada, se pasa a INC_HORA
  315.         goto    INC_HORA                ; Incrementa segundos, minutos y horas. Ajustes y “CHG” a 1
  316.         btfsc   banderas,PSEG   ; Comprobar si se ha pulsado PSEG (Pulsador segundos)
  317.         goto    INC_HORA                ; Se ha pulsado PSEG, (Pul A) y se mostrarán
  318.                                                         ; los segundos en el display
  319. ;
  320. PONER_RELOJ
  321.         movlw   SEGS_INI        ; 196d
  322.         movwf   segundos        ; Inicia los segundos cuando se pone el reloj en hora
  323. ;
  324. PONER_MINUTOS
  325.         btfss   banderas,PMIN   ; Comprobar si se ha pulsado PMIN (Pulsador minutos)
  326.         goto    PONER_HORAS         ; No se ha pulsado PMIN, ir a comprobar estado de PHOR
  327.         movlw   H'AF'                   ; 175d
  328.         movwf   frac_sec            ; Avance rápido del tiempo cuando se ajustan minutos frac_sec = 175
  329.         incfsz  minutos,F               ; Incrementar los minutos
  330.         goto    PONER_HORAS
  331.         movlw   MINS_INI
  332.         movwf   minutos                 ; Iniciar minutos si al incrementar se han desbordado
  333. ;
  334. PONER_HORAS
  335.         btfss   banderas,PHOR   ; Comprobar si se ha pulsado PHOR (Pulsador horas)
  336.         goto    OBTENER_H_M             ; No se ha pulsado PHOR, no se cambian las horas
  337.         movlw   H'7F'                   ; 127d
  338.         movwf   frac_sec                ; Avance rápido del tiempo cuando se ajustan horas frac_sec = 127
  339.         incfsz  horas,F                 ; Incrementar la hora
  340.         goto    OBTENER_H_M
  341.         movlw   HORS_INI
  342.         movwf   horas                   ; Iniciar la hora si al incrementar se han desbordado
  343.         goto    OBTENER_H_M            
  344. ;
  345. INC_HORA        ; Incrementar segundos, minutos y horas
  346.                         ; Ajustes cada minuto, hora y 12 horas
  347.         bsf             banderas,CHG    ; Se especifica que se ha producido un cambio
  348. ;
  349.         incfsz  segundos,F              ; Como ha pasado un segundo se incrementa "segundos"
  350.         goto    COMPROBAR_CHG
  351.         movlw   SEGS_INI                ; Se ha desbordado "segundos" y se reestablece el valor inicial
  352.         movwf   segundos                ; de "segundos" para la próxima vuelta
  353. ;
  354.         movlw   ADJMIN                  ; Se resta 9 a "frac_sec" cada minuto para los ajustes de tiempo
  355.         subwf   frac_sec,F              ; El minuto será 9 "frac_sec" más largo
  356. ;
  357.         incfsz  minutos,F               ; Se añade 1 minuto
  358.         goto    COMPROBAR_CHG
  359.         movlw   MINS_INI                ; Se ha desbordado "minutos" y Se reestablece el valor inicial
  360.         movwf   minutos                 ; de "minutos" para la próxima vuelta
  361. ;
  362.         movlw   ADJHOR                  ; Se suma 34 a "frac_sec" cada hora para los ajustes de tiempo
  363.         addwf   frac_sec,F              ; La hora será 34 "frac_sec" más corta
  364. ;
  365.         incfsz  horas,F                 ; Se añade 1 hora
  366.         goto    COMPROBAR_CHG
  367.         movlw   HORS_INI                        ; Se ha desbordado "horas" y se reestablece el valor inicial
  368.         movwf   horas                   ; de "horas" para la próxima vuelta
  369.         movlw   ADJDIA                  ; Se resta 3 a "frac_sec" cada 12 horas para los ajustes de tiempo
  370.         subwf   frac_sec,F              ; Cada 12 horas se añadirán 3 "frac_sec"
  371. ;
  372. ; Se comprueba el estado de “CHG” por si se ha activado
  373. ; algún pulsador o es necesario actualizar los valores
  374. ; de la hora que tienen que mostrarse en los displays
  375. ; Se actualiza hora, displays y pulsadores cada 4,096 ms (244 veces por segundo)
  376. COMPROBAR_CHG  
  377.         btfss   banderas,CHG    ; Si no se han activado pulsadores ni ha cambiado la hora
  378.         goto    DISPLAY_PUL             ; se salta a DISPLAY_PUL, que principalmente refresca uno de los
  379.                                                         ; displays cada vez que se accede a ella y escanea pulsadores.
  380. ;
  381. COMPROBAR_SEG   ;  Se comprueba si se activo el pulsador de segundos (Pul A)
  382.                                 ; para mostrar los segundos en el display
  383.         btfss   banderas,PSEG
  384.         goto    OBTENER_H_M             ; No estaba pulsado PSEG
  385.         movlw   H'00'                   ; Se mostrarán los segundos en el display de minutos
  386.         movwf   digito2                 ; Variables "digito2" a 0
  387.         movwf   digito3                 ; Variables "digito3" a 0
  388.         movwf   digito4                 ; Variables "digito4" a 0
  389.         movlw   SEGS_INI
  390.         subwf   segundos,W
  391.         movwf   digito1                 ; Se guarda temporalmente el número de segundos en “digito1”
  392.         goto    DIV_DIGITOS            
  393. ;
  394. OBTENER_H_M
  395.         movlw   HORS_12H
  396.         subwf   horas,W
  397.         movwf   digito3         ; La variable digito3 almacena temporalmente el valor para las horas
  398.         movlw   MINS_INI
  399.         subwf   minutos,W
  400.         movwf   digito1         ; La variable digito1 almacena temporalmente el valor para los minutos
  401. ;
  402. DIV_DIGITOS             ; Divide los segundos o los minutos y las horas en dígitos independientes
  403.                                 ; ejemplo, [14] lo pasa a [1]-[4]
  404.         movlw   H'00'
  405.         movwf   digito4         ; Se ponen a cero las posiciones de las decenas
  406.         movwf   digito2         ; para el caso de que no se incrementen
  407.         movlw   H'02'
  408.         movwf   conta1          ; Bucle para convertir cada número (segundos o minutos y horas)
  409.         movlw   digito1         ; Dirección de digito1 en FSR para usar INDF
  410.         movwf   FSR                     ; La primera vez, FSR = digito1 (minutos o segundos) y la segunda vez FSR = digito3 (horas)
  411.         goto    LOOP           
  412. ;
  413. LOOP2   ; Este LOOP se utiliza para las horas después de trabajar con los minutos o los segundos
  414.         movlw   digito3
  415.         movwf   FSR                    
  416. ;
  417. LOOP    ; Este LOOP se utiliza primero para los minutos o los segundos y después para las horas
  418.         movlw   D'10'                   ; Averiguar cuantas "decenas" hay en el número
  419.         subwf   INDF,F                  ; En cada LOOP restar 10 al número
  420.         btfsc   STATUS,C        ; Se comprueba "C", que se pone a 1 si en la resta no se ha
  421.                                                         ; producido llevada
  422.         goto    INC_DECENAS     ; C = 1 por lo que se añade 1 a la posición de las decenas
  423.         addwf   INDF,F                  ; C = 0, no se incrementan las decenas y se suma 10 para restaurar
  424.                                                         ; las unidades
  425.         goto    PROX_NUM
  426. ;
  427. INC_DECENAS
  428.         incf    FSR,F           ; El puntero apunta a la primera posición de las decenas
  429.         incf    INDF,F          ; Se añade 1 a las decenas
  430.         decf    FSR,F           ; Se restaura el valor de INDF para apuntar al número
  431.         goto    LOOP            ; para la próxima resta hasta que se termine
  432.                                                 ; Con "goto LOOP" se vuelve a comprobar si es necesario
  433.                                                 ; sumar uno a la decena cada vez que esta se ha incrementado
  434. ;
  435. PROX_NUM        ; Próximo número, primero ha sido segundos o minutos y luego horas
  436.         decfsz  conta1,F
  437.         goto    LOOP2
  438. ;
  439. CONVER_COD_7S   ; Convierte cada dígito a código 7 segmentos para los displays
  440.         movlw   digito1
  441.         movwf   FSR             ; Coloca la dirección del primer digito (digito1) en FSR
  442.         movlw   H'04'
  443.         movwf   conta1  ; Prepara la variable conta1 para el bucle de los 4 displays
  444. ;
  445. PROX_DIGITO
  446.         movf    INDF,W          ; Obtener el valor de la variable "digito" actual
  447.         call    CODIGO_7S       ; LLamar a la rutina de conversión a código 7 segmentos
  448.         movwf   INDF            ; Colocar en la variable "digito" el código 7 segmentos devuelto
  449.         incf    FSR,F           ; Incremente INDF para el próximo "digito"
  450.         decfsz  conta1,F        ; Permitir que conta1 de sólo 4 vueltas
  451.         goto    PROX_DIGITO
  452. ;
  453. BORRAR_CERO             ; Si hay un cero en el display de las decenas de hora
  454.                                 ; no se muestra (borrado de los ceros a la izquierda)
  455.         movlw   CERO
  456.         subwf   digito4,W
  457.         btfss   STATUS,Z
  458.         goto    BORRAR_CERO_SEG
  459.         movlw   SEGM_OFF
  460.         movwf   digito4
  461. ;
  462. BORRAR_CERO_SEG
  463.         btfss   banderas,PSEG   ; Si está pulsado PSEG no se muestra nada en el display de la
  464.         goto    DISPLAY_PUL             ; posición de la unidad de hora.
  465.         movlw   SEGM_OFF                ; Contando con BORRAR_CERO, esto significa que sólo se
  466.         movwf   digito3                 ; mostrarán los segundos.
  467.         movwf   digito4                 ;****************************Miguel Oct 31 2016
  468. ;
  469. DISPLAY_PUL             ; Se borran los bits de flag para actualizar su estado
  470.                                 ; Escanea pulsadores, si alguno está pulsado se pone a 1
  471.                                 ; el pulsador que le correspoda así como "P_ON" y "CHG"
  472.                                 ; Muestra los dígitos correspondientes a los segundos o a
  473.                                 ; los minutos y horas en el display que corresponda.
  474. ;
  475.         movlw   B'00000000'
  476.         movwf   banderas        ; Se borran los bits de flag para actualizar su estado
  477. ;
  478.         ; Apagar los displays
  479.         movlw   DSPOFF
  480.         movwf   PORTA          
  481. ;
  482.         ; Apagar los segmentos respetando separador horas-minutos
  483.         movlw   SEGM_OFF        ; Respeta valor RB0
  484.         xorwf   PORTB, w
  485.         andlw   B'11111110'     ;  Poner "1" el la posición del bit a copiar
  486.         xorwf   PORTB, f
  487. ;
  488.         ; Configurar los bits 1, 2 y 3 de PORTB como entrada
  489.         bsf             STATUS,RP0      ; Activa el banco 1.
  490.         movlw   PULSADOR
  491.         movwf   TRISB           ; Se configuran los bits 1, 2 y 3 de PORTB como entrada
  492.         bcf             STATUS,RP0      ; Activa el banco 0.
  493.         nop             ; Las instrucciones "nop" pueden no ser necesarias.
  494.         nop             ; En principio proporcionan el tiempo suficiente para que los
  495.         nop             ; estados anteriores de las salidas se actualicen a través de
  496.         nop             ; las resistencias de 10K (y de las de 820 ohm si está activado
  497.         nop             ; algún pulsador) antes de leer las patillas del puerto.
  498. ;
  499. COMPROBAR_PSEG  ; Se comprueba Pulsador PSEG
  500.         btfss   PORTB,1
  501.         goto    COMPROBAR_PMIN
  502.         bsf             banderas,CHG
  503.         bsf             banderas,PSEG
  504.         bsf             banderas,P_ON
  505. ;
  506. COMPROBAR_PMIN  ; Se comprueba Pulsador PMIN
  507.         btfss   PORTB,2
  508.         goto    COMPROBAR_PHOR
  509.         bsf             banderas,CHG
  510.         bsf             banderas,PMIN
  511.         bsf             banderas,P_ON
  512. ;
  513. COMPROBAR_PHOR  ; Se comprueba Pulsador PHOR
  514.         btfss   PORTB,3
  515.         goto    ACTIVAR_SEGM
  516.         bsf             banderas,CHG
  517.         bsf             banderas,PHOR
  518.         bsf             banderas,P_ON
  519. ;
  520. ACTIVAR_SEGM    ; Se coloca en PORTB el valor para los segmentos del display actual
  521.         bsf             STATUS,RP0      ; Activa el banco 1.
  522.         movlw   H'00'
  523.         movwf   TRISB           ; Puerto B como salida
  524.         bcf             STATUS,RP0      ; Activa el banco 0.
  525. ;
  526.         ; Se determina que display debe actualizarse, es decir, que dato debe
  527.         ; presentarse en el puerto B y se establece el siguiente display
  528.         btfss   display,0       ; Si es el primer display (decena de hora) tomar digito4
  529.         movf    digito4,W
  530.         btfss   display,1       ; Si es el segundo display (unidad de hora) tomar valor digito3
  531.         movf    digito3,W
  532.         btfss   display,2       ; Si es el tercer display (decena de min/seg) tomar valor digito2
  533.         movf    digito2,W
  534.         btfss   display,3       ; Si es el cuarto display (unidad de min/seg) tomar valor digito1
  535.         movf    digito1,W
  536. ;
  537.         ; Entregar el valor en puerto B y respetar valor RB0
  538.         xorwf   PORTB, w
  539.         andlw   B'11111110'     ;  Poner "1" el la posición del bit a copiar
  540.         xorwf   PORTB, f
  541. ;
  542.         btfsc   frac_sec,7      ; Establecer el separador de horas y minutos a un 50%
  543.         bcf             PORTB,0         ; del ciclo (1/2 segundo encendido, 1/2 segundo apagado)
  544. ;
  545.         comf    display,w       ; Tomar el valor del display que debe habilitarse
  546.         movwf   PORTA           ; Cada display se “enciende” con una cadencia de 244 Hz / 4 = 61 Hz  
  547.         ; Cada display se “enciende” con una cadencia de 244 Hz / 4 = 61 Hz  
  548.         ; En este momento están encendidos los segmentos correspondientes
  549. ;
  550.         rlf             display,F       ; Rota display 1 bit a la próxima posición
  551.         bsf             display,0       ; Asegura un 1 en la posición más baja de display (luego se hará 0 si es necesario)
  552.         btfss   display,4       ; Comprueba si el último display fue actualizado
  553.         bcf             display,0       ; Si lo fue, se vuelve a habilitar el primer display
  554.                                                 ; La variable display va cambiando:
  555.                                                 ;       1111 1101
  556.                                                 ;       1111 1011
  557.                                                 ;       1111 0111
  558.                                                 ;       1110 1110
  559.                                                 ;       1101 1101
  560.                                                 ;       1011 1011
  561.                                                 ;       0111 0111
  562.                                                 ;       1110 1110
  563.                                                 ; Sólo valen los 4 bits menos significativos
  564. ;
  565.         goto    PRINCIPAL       ; Volver a realizar todo el proceso
  566. ;
  567.     END

elreypic.


 

anything