Primero de todo buenas.
He he escrito el siguiente programilla, el qual es medio reloj:
///////////////////
list P=16f84
#INCLUDE p16f84.inc
__CONFIG _CP_OFF & _PWRTE_OFF & _WDT_OFF & _XT_OSC
CBLOCK 0x0C
ENDC
ORG 0
goto START
ORG 4
goto INTERRUPCIO_TIMER
SEGONS EQU 0x0F
MINUTS EQU 0x10
HORES EQU 0x11
INICI EQU 0x15
PARADA EQU 0x16
INICI_VAR EQU 0x18
PARADA_VAR EQU 0x19
VARI EQU 0x17
RETARD_POLSADOR EQU 0x20
SUB_RETARD EQU 0x21
MOSTRA_DISPLAY EQU 0x22
START
bsf 0x03,5
;entrem a el banc 1
clrf 0x05 ;Activem els bits del port a com entrada
;el port a com a sortida
movlw 0x03
movwf PORTB
movlw 0x17 ;assigna el prescaler i altres opcions en
movwf 0x81 ;en el registre option
bcf 0x03,5 ;es passa al bank 0
movlw d"61" ;Envia un valor definit per crear 50ms en el registre TM
movwf 0x01 ;R0 per tal de la interrupcio es faci cada 50ms
movlw 0xA0 ;activem els bits de intcon per poder usar la
movwf 0x0B ;interrupció del timer
movlw 0x0A ;Es guarda .10 per tal de crear un bucle
movwf 0x0D ;
movlw 0x04 ;Per defecte es guarda 4 hores per a partir de les quals
movwf INICI ;es donarà senyal al rele
movwf INICI_VAR
movlw 0x01 ;Per defecte el rele es desactiva al cap d"una hora dese
movwf PARADA ;que es va activar el rele
movwf PARADA_VAR
movlw 0x14 ;Byte de memoria per que es s"augmenti un segon cada vin
movwf 0x0E ;t interrupcions de timer.
movlw d"61" ;Tornem a reposar el timer
movwf 0x01
movlw 0x03
movwf RETARD_POLSADOR
movlw 0x8
movwf SUB_RETARD
;;;;;;FI DE VARIABLES
;;;EL COS DEL PROGRAMA
MAIN
btfss PORTB,0 ;Mira si s"ha apretat el polsador 1
goto PULS_1
btfss PORTB,1 ;Mira si s"ha apretat el polsador 2
goto PULS_2
btfsc VARI,3
call ENVIA_UNITATS
call ENVIA_DESENES
btfsc VARI,4
goto ACTIVA_RELE
goto DESACTIVA_RELE
goto MAIN
;;;;;;FI MAIN
;;;;A PARTIR D"AQUI FUNCIONS
ENVIA_UNITATS
bcf VARI,3
movf INICI_VAR,0
btfsc VARI,5 ;Si VARI 5 està en 1 s"envia les hores de per parar als displays
movf PARADA_VAR,0
CALL BINARY_TO_BCD
movf UNITATS,0
movwf 0x05
bcf 0x06,7
bsf 0x06,6
return
ENVIA_DESENES
bsf VARI,3
movf INICI_VAR,0
btfsc VARI,5 ;Si el bit 5 de VARI està en 1 no s"envia les hores de INICI als displays
movf PARADA_VAR,0
call BINARY_TO_BCD
movf DESENES,0
movwf 0x05
bcf 0x06,6
bsf 0x06,7
return
PULS_1
call BUCLE_REBOTS
bcf VARI,5 ;Si s"estava mostrant les hores de parada, al apretar el pulsador es torenen a mostrar les hores de inici
movlw 0x18 ;Mira si que INICI No sigui major que 24 hores
subwf INICI,0
btfsc STATUS,Z
goto RESET_INICI
incf INICI,1 ;Incrementa INICI cada vegada que s"apreta boto
movf INICI,0 ;Copia el contingut en INICI_VAR
movwf INICI_VAR
goto MAIN
RESET_INICI
movlw 0x04 ;Com que la variable INICI ha arribat a 24 es posa a 4
movwf INICI
movwf INICI_VAR ; Es fa copia de INICI
goto MAIN
;Quan s"apreta el pulsador dos
PULS_2
CALL BUCLE_REBOTS
bsf VARI,5 ;Bit que fa que es mostri en els displays els numeros de parada
movlw 0x03 ;resta 3 a PARADA perque parada no sigui major a 3
subwf PARADA,0
btfsc STATUS,Z
goto RESET_PARADA
incf PARADA,1
movf PARADA,0
movwf PARADA_VAR
goto MAIN
RESET_PARADA
movlw 0x01
movwf PARADA
movwf PARADA_VAR
goto MAIN
;Fi funció pulsador dos
ACTIVA_RELE
bsf PORTB,2
goto MAIN
DESACTIVA_RELE
bcf PORTB,2
goto MAIN
;MOSTRA_DISPLAY_INICI
; movlw INICI
; CALL BINARY_TO_BCD
; return
;;;;CALL DEL TIMER
INTERRUPCIO_TIMER
call RETARD
call MINI_RETARD
nop
nop
nop
movlw d"63"
movwf 0x01
movlw d"14"
;Mirem si ha passat un segon
decfsz 0x0E,1
goto FI_INTERRUPCIO ;acaba la interrupció perque encara no s"ha gen
;erat la interrupciói
movlw 0x14 ;Recarreguem el byte de memòria 0x0E per que sols pugui
movwf 0x0E ;venir aquí quan han passat 20 timers
nop
incf SEGONS,1 ;Incrementem el byte de mèmoria per contar els segons.
btfss VARI,5 ;Si VARI 5 està en 0 s"en va directament a BUCLE_segons
goto BUCLE_segons
incf MOSTRA_DISPLAY,1
movlw 0x0A
subwf MOSTRA_DISPLAY,0
btfss STATUS,2
goto BUCLE_segons
bcf VARI,5
clrf MOSTRA_DISPLAY
;Rutina per mirar si tenim un minut
BUCLE_segons
movlw 0x3C ;Resta 60 a SEGONS, per saber si dona 0
subwf SEGONS,0
btfss 0x03,0
goto FI_INTERRUPCIO
incf MINUTS,1 ;Augmenta els minuts passats
clrf SEGONS ;Posa a 0 els segons
bcf 0x03,0 ;Posa a 0 el bit de Z
;Rutina per mirar si ha passat una hora
movlw 0x3C ;Resta 60 a MINUTS, per saber si dona 0
subwf MINUTS,0
btfss 0x03,0
goto FI_INTERRUPCIO
incf HORES,1
clrf MINUTS
bcf 0x03,0
decf INICI_VAR,1
btfsc STATUS,2 ;Si han passat les hores establertes en INICI, s"activa el bit 4 de Vari
bsf VARI,4 ;per tal de activar el relé
btfsc VARI,4 ;Decrementa PARADA_VAR per saber si ha arribat a 0
decf PARADA_VAR,1
btfsc STATUS,2 ;Si arriba a 0 desactiva la variable VARI, per saber que es te que parar el relé
bcf VARI,4
;;mira si han passat 12 hores
movlw 0x0C
subwf HORES,0
btfss 0x03,0
goto FI_INTERRUPCIO
bcf 0x03,0 ;Posa a 0 el bit Z
clrf SEGONS
clrf MINUTS
clrf HORES
FI_INTERRUPCIO
bcf 0x0B,2
retfie
;;;;FINAL INTERRUPCIÓ TIMER
RETARD
;Retard per fer el els 50ms exactes
movlw 0x04
movwf 0x0D
BUCLE
movlw 0x29
movwf 0x0C
SUB_BUCLE
decfsz 0x0C,1
goto SUB_BUCLE
decfsz 0x0D,1
goto BUCLE
return
;Fi de retard
MINI_RETARD
movlw 0x15
movwf 0x24
BUCLE_MINI_RETARD
decfsz 0x24,1
goto BUCLE_MINI_RETARD
return
;Rutina per passar de binari a bcd
BINARY_TO_BCD
clrf UNITATS
clrf DESENES
UNITATS EQU 0x12
DESENES EQU 0x13
CENTENES EQU 0x14
movwf UNITATS ;Guardem el número a convertir en les UNITATS
BUCLE_BCD
movlw 0x0A
subwf UNITATS,1 ;Resta .10 a les UNITATS
btfss STATUS,C ;Comprova si les unitats són més petites que 10
goto FI_BIN_BCD ;Com que es més petit s"acaba
addwf UNITATS,1 ;Recupera els .10 restats en principi
subwf UNITATS,1 ;Resta .10 a les UNITATS
incfsz DESENES,1
goto BUCLE_BCD
incf CENTENES,1
clrf DESENES
goto BUCLE_BCD
FI_BIN_BCD
movlw 0x0A ;Recupera els .10 restats per comprovar si es més gran
addwf UNITATS,1
return
;;;FI RUTINA PER PASSAR DE BINARY A BCD
BUCLE_REBOTS
movlw 0xC3
movwf RETARD_POLSADOR
movlw 0xC3
movwf SUB_RETARD
B_REBOTS
decfsz RETARD_POLSADOR,1
goto SUB_REB
goto FI_RETARD
SUB_REB
decfsz SUB_RETARD,1
goto SUB_REB
goto B_REBOTS
FI_RETARD
RETURN
end
////////////////
Por ahora lo uso como temporizador i prácticamente funciona todo. El problema está en que cada hora saca por el PORTA las horas que quedan para activar un relé en BCD. En el simulador usando el STOPWATCH le quedan microSegundos para que la hora sea exacta. Pero si lo ejecuto realmente en el circuito se atrasa un minuto y no le encuentro la solución.
El circuito usa un Cristal de 4Mhz i oscila a 4,0001 Mhz.
Con todo esto no se que puede pasar???