Autor Tema: interrupción analogico digital pic16f887  (Leído 3770 veces)

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

Desconectado lutgaru

  • PIC10
  • *
  • Mensajes: 5
interrupción analogico digital pic16f887
« en: 02 de Octubre de 2016, 12:36:37 »
hola foro
me podrian ayudar con el siguiente código de convertidor analogico digital usando su interrupción, en teoria deberia de funcionar pero a la hora d la simulación no lo hace, no puedo ver en que me equivoque, espero me puedan ayudar:
Código: [Seleccionar]
LIST   p=16F887  ;Tipo de micro
INCLUDE   "P16F887.inc" ;File include
;<<<<<<------------------------Define palabra de configuracion -------------------------->>>>>>>   
     __CONFIG _CONFIG1, _FOSC_INTRC_NOCLKOUT & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CP_ON & _CPD_OFF & _BOREN_OFF & _IESO_OFF & _FCMEN_OFF & _LVP_OFF
 
;------------------------------------------------------------------------------------------

    cblock 0x20
    d1
    endc

    org     0x00
    goto    INICIO
    org     0x04
    goto    INTERRUPCION ;direccion de interrupcion. 0x04
    ; Se transmite via Serie el dato que esta en el registro W
;------------------------------------------------------------------------------------------
 
 
INICIO
bsf STATUS,RP0    ;Cambio al banco 1
CLRF    TRISB
CLRF TRISC
bcf STATUS,RP0   
bcf STATUS,RP1    ;Cambio al banco 0
MOVLW 0XFF
MOVWF PORTB
MOVWF PORTC

 
;----------------------------------------------------------------------------------------------------
;inicia ADC
BANKSEL     ADCON0 ;
MOVLW     B'11000001' ;ADC Frc clock,
MOVWF     ADCON0 ;AN0, On
BANKSEL     ADCON1 ;
MOVLW     B'10000000' ;right justify
MOVWF     ADCON1 ;Vdd and Vss as Vref
BANKSEL     TRISA ;
BSF     TRISA,0 ;Set RA0 to input
BANKSEL     ANSEL ;
BSF     ANSEL,0 ;Set RA0 to analog
;----------------------------------------------------------------------------------------------------
;configura interrupcion
;BANKSEL     ADCON1 ;
;MOVLW     B'10000000' ;right justify
;MOVWF     ADCON1 ;Vdd and Vss as Vref
BANKSEL     PIE1;
BSF     PIE1,ADIE     ;HABILITAMOS EL REGISTRO DE INTERRUPCION
BANKSEL     PIR1
BCF     PIR1,ADIF
BANKSEL     INTCON ;
bsf INTCON, PEIE ; Enable peripheral interrupts
bsf INTCON, GIE ; Enable global interrupts
;BANKSEL     TRISA ;
;BSF     TRISA,0 ;Set RA0 to input
;BANKSEL     ANSEL ;
;BSF     ANSEL,0 ;Set RA0 to analog
CALL     DELAY ;Acquisiton delay
;BANKSEL     ADCON0 ;
;MOVLW     B'11000001' ;ADC Frc clock,
BANKSEL     ADCON0
bsf     ADCON0,2 ; Start conversion (set GO)


 
principal   goto    principal

;-------------------------------------------------------------------------------------------
INTERRUPCION
call     DELAY
BSF     ADCON0,GO ;Start conversion
BTFSC     ADCON0,GO ;Is conversion done?
GOTO     $-1 ;No, test again
bcf     PIR1,ADIF ;restauramos bandera
BANKSEL    ADRESH ;
MOVF     ADRESH,W ;Read upper 2 bits
MOVWF     PORTC ;store in GPR space
BANKSEL    ADRESL ;
MOVF     ADRESL,W ;Read lower 8 bits
MOVWF     PORTB ;Store in GPR space
 RETFIE
;--------------------------------------------------------------------------------------------
 
DELAY
;16 cycles
movlw 0x05
movwf d1
Delay_0
decfsz d1, f
goto Delay_0

;4 cycles (including call)
return
     
END     
« Última modificación: 02 de Octubre de 2016, 12:47:46 por lutgaru »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:interrupción analogico digital pic16f887
« Respuesta #1 en: 02 de Octubre de 2016, 14:21:35 »
En teoria es un mal codigo. Hay cosas mal implementadas tambien y hay errores.

Cosas que encontre y que deberias solucionar:

1- No estas guardando W y STATUS al comienzo de la rutina de interrupcion y saliendo de la misma. Aunque esto no es tu problema, lo va a ser si es que en "principal" tenes codigo y no solo un GOTO como ahora. Aunque puede llegar a tener influencias si no lo usas y no estas conciente de como funciona una interrupcion en e  codigo que pasaste (ver el punto 6 para mas informacion)

2- Estas usando un delay DENTRO de la interrupcion, no deberias hacerlo, si tu circuito requiere mas tiempo de adquisicion de lo que puede darle el ADC solo, entonces o usas un delay en "principal" y luego activas el GO del ADC (dentro de principal), o usas un timer para activar el GO, ya que este ADC no permite elegir el tiempo de adquisicion.

3- Estas suponiendo que al entrar a la interrupcion es para que COMIENZE el ADC, y no es asi. Cuando entra a la interrupcion es por que se completo, FINALIZO la conversion del ADC. Por lo tanto apenas entras no activas el GO de nuevo y esperas, sino que tomas el dato, lo guardas, luego activas el GO y salis. Cuando se termine de convertir y tengas un valor va a entrar nuevamente.
Como te decia antes, si lo que vos intentas no es un muestreo continuo, es decir que apenas termine el ADC comienze de vuelta o no te dan los tiempos por que requiere un tiempo de adquisicion mayor, deberias aplicar algo de lo que dije en el punto 2. Es decir que un timer ( en su interrupcion) ponga a 1 el bit GO y salga de la interrupcion, luego entraria de nuevo cuando se complete el ADC.

4- Asi como tenes el codigo, cuando entra a la interrupcion, inicias el ADC, espera hasta que termine el ADC, limpias la bandera y salis. A partir de aca nunca mas va a entrar a esa rutina de interrupcion por que nunca se va a completar conversion del ADC, ya que nunca se inicio.

5- Esto es un error:

Código: ASM
  1. bsf         ADCON0,2 ; Start conversion (set GO)

podrias haber usado ADCON0,GO y no hubieras tenido ese problema. El bit 2 corresponde a CHS0 que es el canal. tal ves te confundiste por empezar a contar desde 1 y no 0. El bit que buscas es el 1.

6-
En la rutina de interrupcion, tomas de ADRESL que esta en el banco 1 e intentas ponerlo en el PORTB del banco 0, lo unico que estas haciendo aca es escribir realmente TRISB y no PORTB por que no cambiaste de banco.

Esto con el problema numero 1 trae MAS problemas. Sigamos la linea de flujo del programa:
- Inicias ADC
- Entras a la interrupcion cuando se termina
- Llamas a DELAY que tiene una variable en el banco 0
- Luego Usas ADCON0, ADRESH y PIR1 del banco 0
- Cambias al banco 1 para acceder a ADRESL, aca tu error de no pasar al banco 0 para ponerlo en PORTB (numero 5 de esta lista)
- Salis de la interrupcion. Suponete que iniciaste la conversion y entre nuevamente a la interrupcion ( numero 4  de esta lista)
- Entras a la interrupcion, llamas a DELAY, pero esta ves estas en el banco 1 y no 0, por lo tanto estas escribiendo en la posicion de memoria 0xA0
- En ves de modificar ADCON0, PIR1 estarias modificando ADCON1 y PIE 1.
- Luego lo demas por el banksel se comporta de manera similar y se repite.

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

PD:
Veo que el delay es de 16 ciclos. Si te pones a pensar al momento que ejecuta la interrupcion, el micro debe tomar la direccion en 0x004, hacer el salto , ya son 2 ahi, luego tenes el guardado de contexto que te va a llevar unos 5 ciclos o 6 tal ves, van 8, luego tenes que guardar los datos de ADRESH y ADRESL con el cambio de banco incluido, tendrias 6 mas aproximadamente. eso te lleva a un totalde 14 ciclos, le pones 2 NOP y le das a GO del ADCON0, y ya tendrias tus 16 ciclos antes del inicio de la nueva conversion.
« Última modificación: 02 de Octubre de 2016, 14:34:56 por KILLERJC »

Desconectado lutgaru

  • PIC10
  • *
  • Mensajes: 5
Re:interrupción analogico digital pic16f887
« Respuesta #2 en: 02 de Octubre de 2016, 15:02:34 »
GRACIAS COMPAÑERO

me apena muchísimo que hayas tenido que corregir mi errores tan desagradables que son, espero que comprendas a este novato, todo lo que dijiste lo entendí perfectamente, lo implementare de inmediato y publicare el código cuando funcione como aporte ya que no e visto nada como mi problema, muchisimas gracias por tu tiempo me as salvado la vida ((:-)) ((:-)) ((:-)) ((:-))

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:interrupción analogico digital pic16f887
« Respuesta #3 en: 02 de Octubre de 2016, 15:24:37 »
No te preocupes nadie nacio sabiendo.

Para el punto 1, busca en el datasheet W_TEMP que seguro te aparece el codigo que debes poner. Microchip te lo facilita.

Si tenes dudas de los nombres de las variables, como es el GO_DONE, podes abrir el archivo .inc que posee las igualdades ( EQU )

Desconectado lutgaru

  • PIC10
  • *
  • Mensajes: 5
Re:interrupción analogico digital pic16f887
« Respuesta #4 en: 02 de Octubre de 2016, 16:40:32 »
gracias a tus consejos e llegado a la segunda versión del código, pero se me sigue pasando algo y no se que es, espero que me puedas ayudar:
Código: [Seleccionar]
LIST   p=16F887  ;Tipo de micro
INCLUDE   "P16F887.inc" ;File include
;<<<<<<------------------------Define palabra de configuracion -------------------------->>>>>>>   
     __CONFIG _CONFIG1, _FOSC_INTRC_NOCLKOUT & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CP_ON & _CPD_OFF & _BOREN_OFF & _IESO_OFF & _FCMEN_OFF & _LVP_OFF
 
;------------------------------------------------------------------------------------------

    cblock 0x20
    d1
    endc

    org     0x00
    goto    INICIO
    org     0x04
    goto    INTERRUPCION ;direccion de interrupcion. 0x04
    ; Se transmite via Serie el dato que esta en el registro W
;------------------------------------------------------------------------------------------
 
 
INICIO
bsf STATUS,RP0    ;Cambio al banco 1
CLRF    TRISB
CLRF TRISC
MOVLW 0xff
MOVWF TRISA
BANKSEL     ANSEL ;
BSF     ANSEL,0 ;Set RA0 to analog
bcf STATUS,RP0   
bcf STATUS,RP1    ;Cambio al banco 0
 
;----------------------------------------------------------------------------------------------------
;inicia ADC
BANKSEL     ADCON0 ;
MOVLW     B'11000001' ;ADC Frc clock,
MOVWF     ADCON0 ;AN0, On
BANKSEL     ADCON1 ;
MOVLW     B'10000000' ;right justify
MOVWF     ADCON1 ;Vdd and Vss as Vref
;----------------------------------------------------------------------------------------------------
;configura interrupcion
BANKSEL     INTCON ;
bsf     INTCON, PEIE ; Enable peripheral interrupts
bsf     INTCON, GIE ; Enable global interrupts
BSF     PIE1,ADIE     ;HABILITAMOS EL REGISTRO DE INTERRUPCION
BANKSEL     PIR1
BCF     PIR1,ADIF   ;apagamos la bandera
CALL     DELAY ;Acquisiton delay
BSF     ADCON0,GO ; Start conversion (set GO)


 
principal   
CALL DELAY
goto    principal

;-------------------------------------------------------------------------------------------
INTERRUPCION
BANKSEL     ADCON0
call     DELAY
; BTFSC     ADCON0,GO ;Is conversion done?
; GOTO     $-1 ;No, test again
BANKSEL     ADRESL ;
MOVF     ADRESL,W ;Read lower 8 bits
BANKSEL     PORTB ;
MOVWF     PORTB ;Store in GPR space
BSF     ADCON0,GO ;Start conversion
BCF     PIR1,ADIF ;restauramos bandera
 RETFIE
;--------------------------------------------------------------------------------------------
 
DELAY
;16 cycles
movlw 0x05
movwf d1
Delay_0
decfsz d1, f
goto Delay_0

;4 cycles (including call)
return
     
END     

aun no e implementado el punto 1 que me proporcionaste pero ya me di cuenta que en datasheet esta, espero que puedas ayudar te lo agradeceria muchisimo
« Última modificación: 02 de Octubre de 2016, 16:42:44 por lutgaru »


 

anything