En ocasiones no funciona, en otros se queda bloqueado y debo estar metiendo y sacando el pic hasta que por casualidad todo funciona. Os paso el programa completo aunque supongo que el problema residirá al principio.
Sin mirar el programa. Si funciona correctamente cada tanto quiere decir que el programa esta bien. Y mas seguramente el problema sea de Hardware, proba poniendo el MCLR en ON, tambien agregando capacidades de desacoplo.
EDIT:Mirando un poco el codigo me encuentro con algunas cosas...
- boton_0 nunca es inicializado a un valor. Mas cuando es usado como indice en una tabla
Int_Rb0
btfss PORTB,0
goto Int_Rb0
call Retardo_2ms
; call Retardo_pulsador
btfss PORTB,0
goto Int_Rb0
incf boton_0,1
movf max_boton_0
btfss STATUS,Z
BCF INTCON,INTF
RETURN
Podes usar retardos si no te afecta en los tiempos pero, ya con el retardo + limpieza de flag al ultimo ya esta.
el MOVF del MAX_BOTON_0 lo veo absurdo ahi aplicado. Imagino que intentaste aplicar un maximo que puede llegar boton_0, pero no veo que influya sobre el incf. El maximo deberia ser una constante y no un registro, al MOVF le falta el W o F, pero por default va a F, asi que estas preguntando si max_boton_0 es 0 y boton_0 no posee limite de incremento... no tiene sentido.
Recomendacion poner W_temp y los mas usados en direcciones de memoria que sean compartidas entre bancos (desde 0x70 a 0x7F, y pueden ser accedidos desde cualquier banco).
Ajuste_fino
decfsz Ajuste,F ; Se crea esta línea para ajustar aún más el tiempo, se predefine en los valores invariables a principio del código
Ajuste fino... no lo es.. tener que usar un delay para hacer el ajuste, por ahi es mejor que confies en el cristal que estes usando. Ademas... Si usas el flag de interrupcion del CCP, no tiene sentido y me explico el porque.. Supongamos que tu flag del CCP es de 200ms y tu delay de es 4ms.
Se va a preguntar por el flag del CCP, este va a actualizarse cada 200ms, graficamente tenes que:
|----------------------|---------------------|--------------------|
200ms 400ms 600ms 800ms
Esto sin el delay.. veremos que pasa poniendole un delay
|----------------------|---------------------|--------------------|
200+4ms 400+4ms 600+4ms 800+4ms
Si te pones a pensar, entre entrada y entrada, siguen existiendo solo 200ms, el delay no afecto en nada.
Si tu idea es usar un delay mas grande que el flag del CCP, entonces no tiene sentido usar el CCP.
EDIT2: Ahora veo el porque del delay ahi, estas mezclando la funcion de incrementar la hora con la de mostrar. Ningun sentido de hacer esto.
-------------------------------------------------
Principal
movf boton_0,w
sublw uno
btfsc STATUS,Z
call Tabla
call Contar_hora
goto Principal
; ================================================================
; Comienza el programa principal.
; ================================================================
Tabla
movf boton_0,W
addwf PCL,F
call Principal
¿Por que hacerlo ciclico asi? Si va a tabla y tiene que volver a Principal, entonces un RETURN, pero no otro CALL.
------------------------------------------
Mostrar_hora
; .............
call Tabla ;tablaSi de Tabla llamo a Mostrar_hora, no deberia jamas de Mostrar_hora llamar a Tabla. Esto es lo mismo que antes, y pide a gritos que si no esta muy bien programado termines con un call stack overflow.
Te puedo decir que uses GOTO, pero significa pensar de otra forma el programa.
Por ejemplo linterna, running_mode, y algunos mas que tienen un CALL Principal, se beneficiarian si tuvieran un RETURN y en TABLA fueran GOTO, de esa forma vuelve a Principal por si solo y ejecutaria el CALL Contar_hora, ya que esta volviendo del CALL Tabla. Y como ves, volves a Principal.
------------------------------------------
Por ahora no poseo mas tiempo, para seguir viendolo. Estas son algunas de las cosas que vi.
pero por lo visto, por ahi sugiero que uses una interrupcion del CCP, con un valor comodo de milisegundos que te sirva tanto para el mostrar en los displays como para la demora, es decir que ese valor pueda dividirse y dar enteros para estos casos, luego aplicar contadores.
Y acordate, que cada ves que haces un CALL, se guarda la direccion en un stack que es fijo en cantidad, de alli solo se saca con un RETURN, si un CALL no encuentra un RETURN quiere decir que estas llenandolo y pronto va a llenarse por completo. Una ves lleno se empieza a sobreescribir lo que estaba, y esto implica ya un mal funcionamiento al ejecutar un RETURN por ejemplo.