Autor Tema: Problemas con pic al cambiar la alimentación o quemar el pic.  (Leído 108 veces)

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

Desconectado Fulguitron

  • PIC16
  • ***
  • Mensajes: 118
    • Disfruta de mi blog, hobbies y gadgets diferentes y poco comunes.
Buenos días. Tengo un problema con el pic16F628. Cuando quemo el pic o se me acaba la pila de botón nunca empieza el programa a la primera correctamente. 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.

Alguna sugerencia??

Código: [Seleccionar]

; =====================================================================
; Funciones:
; Hora
; runing mode
; linterna
; ajuste de hora y minutos
; Version: Bonwatch_1_3
; ======================================================================

__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _INTOSC_OSC_NOCLKOUT & _DATA_CP_OFF & _LVP_OFF & _MCLRE_OFF
LIST    P=16F628A
INCLUDE  <P16F628A.INC>

CBLOCK  0x20
Status_temp
W_temp
boton_0 
segundos
minutos
horas
running
contador
Ajuste
Ajuste_1
Ajuste_2
dosleds
max_boton_0
; R_ContA ; Contadores para los retardos.
ENDC
; ====================================================================
; Zona donde se guardan los valores invariables.
; ====================================================================
Max_horas EQU d'13' ; Hora máxima para poner a 1 horas después de las 12 horas.
Max_minutos EQU d'60'
Max_segundos EQU d'60'
Max_ajuste_hora EQU d'12'
Max_ajuste_minutos EQU d'60'
uno EQU d'1'
; =========================================================
; Configuración de la interrupción, entradas, salidas, timer.
; ==============================================================

ORG    0x0000      ; Vector de reset
goto Inicio
ORG 0X0004 ; Vector de interrupcion
goto Interrupcion

Inicio
 
bsf STATUS,RP0
clrf TRISA
movlw b'00000011' ; Configurado como salidas excepto los dos primeros.
movwf TRISB
movlw b'00000000' ; Configurado como salidas
movwf TRISA
bcf STATUS,RP0

    movlw   0x07
    movwf   CMCON

movlw b'10010000'
movwf INTCON
movlw   b'00111100'    ; ('00111100')Se selecciona TMR1, preescaler de 1/8, modo temporizador.-
movwf   T1CON
  movlw   b'00001011'  ; Se configura CCP modo captura cada flanco de subida.-
  movwf   CCP1CON

movlw   b'11111100' ; 0xF4 244
movwf   CCPR1H
movlw   b'00110111'    ; 0x24 36
movwf   CCPR1L
CLRF    TMR1H
CLRF    TMR1L         
bsf T1CON,TMR1ON ; Uso del timer interior a 38khz.
BCF PCON, OSCF
clrf segundos

; =================================================================
; Activamos la interrupción
; =================================================================
BCF     INTCON,INTF     ; Activo interrupcion de RB0/Flanco descendente
BSF     INTCON,INTE
BSF     INTCON,GIE      ; Habilitamos interrupciones globales
;===================================================================
; Zona del banco de memorias de los diferentes registros.
; ====================================================================

movlw d'2'
movwf max_boton_0
movlw d'2'
movwf contador
; movlw d'5'
; movwf Ajuste
; movlw d'125'
; movwf Ajuste_1
movlw d'15'
movwf running
movlw d'51'
movwf dosleds

; =============================================================
; Ponemos en hora el reloj.
; ==============================================================

movlw d'10' ; Aquí se ajusta la hora
movwf horas
movlw d'49' ; Aquí se ajustan los minutos
movwf minutos

; =======================================================================
; Una vez el boton_0 está a 1 mostramos la hora y los minutos
; =======================================================================

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
call Mostrar_hora
call running_mode
call linterna
call ajustar_hora
call ajustar_minutos
goto Tabla

; ==============================================================
; Se encienden los seis leds de forma intermitente
; ==============================================================
running_mode
movf running,W
movwf PORTA
movwf PORTB
call Contar_hora
clrf PORTA
clrf PORTB
call Contar_hora
btfss PORTB,1
goto clear_running_mode
goto running_mode

clear_running_mode
clrf PORTA
clrf PORTB
clrf boton_0
call Principal

; ==============================================================
; Se encienden los dos leds RGB
; ==============================================================
linterna
movf dosleds,W
movwf PORTA
movwf PORTB
call Contar_hora
btfss PORTB,1
goto clear_linterna
goto Tabla

clear_linterna
clrf PORTA
clrf PORTB
clrf boton_0
call Principal

; ============================================================
; Muestra la hora y los minutos
; ============================================================
Mostrar_hora
movf horas,W ; mostramos las horas por el display de leds.
movwf PORTA
movwf PORTB
call Contar_hora ; tiempo en que los leds permanecen encendidos mostrando la hora
clrf PORTA
clrf PORTB
call Contar_hora ; tiempo en que los leds permanecen apagadosd'6'
movf minutos,W ; mostramos lOS minutos por el display de leds.
movwf PORTA
movwf PORTB
call Contar_hora
clrf PORTA
clrf PORTB
call Contar_hora
; Revisa si boton_0 esta pulsado, sino es así, se apagan los leds, si es así se va a tabla.
movf boton_0,w
sublw uno
btfsc STATUS,Z
call clear_boton_0
call Tabla       ;tabla

clear_boton_0
clrf boton_0
call Principal

; ==========================================================================
; Conteo de las horas del reloj y su puesta a cero cuando llega a las 12 horas
; =============================================================================

Contar_hora
inc_segundos

btfss PIR1,CCP1IF
goto inc_segundos
bcf PIR1,CCP1IF
clrf TMR1H
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
goto Ajuste_fino
movlw d'10'
movwf Ajuste

decfsz Ajuste_1,F
goto Ajuste_fino
movlw d'240'
movwf Ajuste_1

decfsz Ajuste_2,F
goto Ajuste_fino
movlw d'125'
movwf Ajuste_2

decfsz contador,F
goto inc_segundos

comp
movlw d'1'
movwf contador

incf segundos,F
movf segundos,W ;revisa si ha llegado a 60 segundos.
sublw Max_segundos
btfss STATUS,Z ; si ha llegado a 60 segundos, se va a inc_minutos, sino return
return

; ================================================================================
; En el momento que los segundos llegan a 60, se incrementa 1 a minutos,
; se revisa si se ha llegado a 60 minutos y se pone a 0 los segundos
; ================================================================================

inc_minutos ; Ponemos a cero los segundos para que empiece el conteo.
clrf segundos
incf minutos ; incrementamos en 1 los minutos.

movf minutos,W
sublw Max_minutos ; revisa si ha llegado a 60 minutos.
btfsc STATUS,Z
goto inc_horas ; si ha llegado a 60 minutos se va a inc_horas.
return


; =================================================================================
; En el momento que los minutos llegan a 60,
; se incrementa 1 en horas y se ponen a 0 los minutos y los segundos.
; ==============================================================================

inc_horas
clrf minutos
incf horas

movf horas,W
sublw Max_horas ; revisa si ha llegado a 60 minutos.
btfsc STATUS,Z
call doce_horas
return
; ========================================================================
; Se ponen a inicio las horas, minutos y segundos
; =======================================================================

doce_horas
movlw d'1'
movwf horas
clrf segundos
clrf minutos
return


; =============================================================
; Ajustar hora
; =============================================================
ajustar_hora
btfss PORTB,0
goto ajustar_minutos
call Retardo_200ms
movf horas,W
movwf PORTA
movwf PORTB
btfsc PORTB,1
goto ajustar_hora
incf horas
call Retardo_500ms
movf horas,W
sublw Max_ajuste_hora
btfsc STATUS,Z
clrf horas
goto ajustar_hora
; =============================================================
; Ajustar minutos
; =============================================================
ajustar_minutos
btfss PORTB,0
goto ajustar_minutos
call Retardo_200ms
btfss PORTB,0
goto Poneracero
movf minutos,W
movwf PORTA
movwf PORTB
btfsc PORTB,1
goto ajustar_minutos
incf minutos
call Retardo_500ms
movf minutos,W
sublw Max_ajuste_minutos
btfsc STATUS,Z
clrf minutos
goto ajustar_minutos
Poneracero
clrf PORTA
clrf PORTB
movlw d'0'
movwf boton_0
goto Principal

; ===========================================================
; Comienzo de la interrupcion
; =============================================================

Interrupcion
; Guardo Contexto
    MOVWF   W_temp
    SWAPF   STATUS,W
    MOVWF   Status_temp
; Comienza el codigo de mi interrupcion

      BANKSEL PIR1
      BTFSC   INTCON,INTF
      CALL    Int_Rb0

; Fin de codigo de interrupcion       
; Devuelvo el contexto

;Fin_interrupcion:

        SWAPF   Status_temp,W
        MOVWF   STATUS

        SWAPF   W_temp,F
        SWAPF   W_temp,W
        RETFIE

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
 
;Retardo_pulsador ; La llamada "call" aporta 2 ciclos máquina.
; nop ; Aporta 1 ciclo máquina.
; movlw d'255' ; Aporta 1 ciclo máquina. Este es el valor de "K".
; movwf R_ContA ; Aporta 1 ciclo máquina.
;Rmicros_Bucle
; decfsz R_ContA,F ; (K-1)x1 cm (cuando no salta) + 2 cm (al saltar).
; goto Rmicros_Bucle ; Aporta (K-1)x2 ciclos máquina.
; return ; El salto del retorno aporta 2 ciclos máquina.
;


INCLUDE <RETARDOS.INC>
END






Disfruta de mi blog, hobbies y gadgets diferentes y poco comunes.

http://hobbiesygadgets.blogspot.com.es/

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 6550
Re:Problemas con pic al cambiar la alimentación o quemar el pic.
« Respuesta #1 en: 06 de Mayo de 2018, 11:39:45 »
Citar
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

Código: ASM
  1. Int_Rb0
  2.         btfss   PORTB,0
  3.         goto    Int_Rb0
  4.         call    Retardo_2ms
  5. ;       call    Retardo_pulsador
  6.         btfss   PORTB,0
  7.         goto    Int_Rb0
  8.         incf    boton_0,1
  9.         movf    max_boton_0
  10.         btfss   STATUS,Z
  11.         BCF     INTCON,INTF    
  12.         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).


Citar
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.

-------------------------------------------------

Citar
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.

------------------------------------------

Código: [Seleccionar]
Mostrar_hora
        ; .............
call Tabla       ;tabla

Si 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.
« Última modificación: 06 de Mayo de 2018, 12:30:29 por KILLERJC »


 

anything