Autor Tema: Problema con #int_AD  (Leído 4768 veces)

0 Usuarios y 3 Visitantes están viendo este tema.

Desconectado iNoXSteeL

  • PIC12
  • **
  • Mensajes: 75
    • La web de InoX
Problema con #int_AD
« en: 20 de Diciembre de 2009, 15:01:29 »
Hola a todos,

Estoy probando la conversión AD de una parte de un programa por separado, pero no lee los valores tal como lo pongo en el código, sin embargo, si incluyo el contenido de #int_AD en el bucle del main, lo lee sin problema.

No se si hago correctamente el uso de la interrupción AD  :oops: , ya que lo intento implementar así para no tener que llamar constantemente a una función de lectura.

Gracias de antemano.

Un saludo.

Código: C
  1. #include <18f4550.h>
  2. #device adc=10
  3. #fuses HS,XT,NOPUT,NOPROTECT,NOMCLR
  4.  
  5. #use delay(clock=12M)
  6. #use fast_io(a)
  7. #use fast_io(d)
  8.  
  9. #include <lcd.c>
  10. #include <math.h>
  11.  
  12. int16 NtcBeta=4050, ReadNtc=0;
  13. float ResNtc=0,Vntc=0,Temp1,Temp2;
  14.  
  15. #int_ad
  16. void LecturaSondas()
  17.  {  
  18.     set_adc_channel(0);
  19.     delay_us(20);
  20.  
  21.     ReadNtc = Read_ADC(ADC_READ_ONLY);
  22.     Vntc = 5.0 * ReadNtc  / 1024.0;
  23.  
  24.     ResNtc =  Vntc * 10000.0  / ( 5.0 - Vntc ) ;
  25.     Temp1 = (1.0 / (((log(ResNtc/20000.0) * (1.0 / NtcBeta) )) + (1 / 298.15))) - 273.15;
  26.    
  27.     Read_ADC(ADC_START_ONLY);
  28.    
  29.     set_adc_channel(1);
  30.     delay_us(20);
  31.    
  32.     ReadNtc = Read_ADC(ADC_READ_ONLY);
  33.     Vntc = 5.0 * ReadNtc  / 1024.0;
  34.  
  35.     ResNtc =  Vntc * 10000.0  / ( 5.0 - Vntc ) ;
  36.     Temp2 = (1.0 / (((log(ResNtc/20000.0) * (1.0 / NtcBeta) )) + (1 / 298.15))) - 273.15;
  37.    
  38.     Read_ADC(ADC_START_ONLY);
  39.  }
  40.  
  41. void main()
  42.    {
  43.    set_tris_b(0x00);
  44.    set_tris_a(0b00000011);
  45.    
  46.    lcd_init();
  47.    
  48.    enable_interrupts(INT_AD);
  49.    enable_interrupts(GLOBAL);
  50.    setup_port_a(AN0_TO_AN1);
  51.    setup_adc(ADC_CLOCK_INTERNAL);
  52.  
  53.    clear_interrupt(INT_AD);
  54.  
  55.   while(1)
  56.     {
  57.      
  58.       lcd_gotoxy(1,1); printf(Lcd_putc,"Temp1 %02.2f",Temp1);
  59.       lcd_gotoxy(1,2); printf(Lcd_putc,"Temp2 %02.2f",Temp2);
  60.  
  61.     }
  62.    }

Desconectado jhozate

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1698
Re: Problema con #int_AD
« Respuesta #1 en: 20 de Diciembre de 2009, 15:15:49 »
nunca he usado la  #int_ad pero sino estoy mal la interrupcion salta cuando la conversion A/D se ha realizado y se pone un bit (ADIF) a "1". Es decir, si tienes habilitada interrupcion glogal, el micro irá al vector de interrupcion solo para avisar que ya finalizó la conversion.

saludos
Ser Colombiano es un Premio, Saludos desde CALI-COLOMBIA

Desconectado iNoXSteeL

  • PIC12
  • **
  • Mensajes: 75
    • La web de InoX
Re: Problema con #int_AD
« Respuesta #2 en: 20 de Diciembre de 2009, 15:40:05 »
nunca he usado la  #int_ad pero sino estoy mal la interrupcion salta cuando la conversion A/D se ha realizado y se pone un bit (ADIF) a "1". Es decir, si tienes habilitada interrupcion glogal, el micro irá al vector de interrupcion solo para avisar que ya finalizó la conversion.

saludos

Entonces, según dices, tendría que hacer la lectura y conversión en otra función y una vez terminada se ejecutará la interrupción AD? es así?

Gracias ;-)

Desconectado gera

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2188
Re: Problema con #int_AD
« Respuesta #3 en: 20 de Diciembre de 2009, 15:45:41 »
Yo tengo la misma duda sobre esa interrupcion. Si la interrupcion AD salta cuando termina la conversion, con q funcion mandamos a convertir? Yo siempre hago la lectura con un read_adc() en el bucle principal.
saludos!

"conozco dos cosas infinitas: el universo y la estupidez humana. Y no estoy muy seguro del primero." A.Einstein

Desconectado jhozate

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1698
Re: Problema con #int_AD
« Respuesta #4 en: 20 de Diciembre de 2009, 15:46:30 »
creo q si los tiempo no son criticos puedes realizar la lectura y poner un delay de 20 Us.
saludos

PD. si la verdad el uso de esa interrupcion yo creo que es como para aprovechar tiempo valioso si se requiere, porque terminada la conversion se esperarian 20 Us y en esos veinte micro segundos podriamos hacer unas cuantas cosas
Ser Colombiano es un Premio, Saludos desde CALI-COLOMBIA

Desconectado jhozate

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1698
Re: Problema con #int_AD
« Respuesta #5 en: 20 de Diciembre de 2009, 16:09:54 »
Yo tengo la misma duda sobre esa interrupcion. Si la interrupcion AD salta cuando termina la conversion, con q funcion mandamos a convertir? Yo siempre hago la lectura con un read_adc() en el bucle principal.
saludos!

rea_adc();
traduce el siguiente assembler
Código: [Seleccionar]
009A:  BSF    1F.2    //poner a uno el bit go/done, es decir  inicializar la conversion
009B:  BTFSC  1F.2  //he aqui donde se queda infinitamente
009C:  GOTO   09B  //esperando a que se ponga a cero el bit go/done
009D:  MOVF   1E,W //lectura del registro adresh

read_adc se encarga de iniciar el conversor y ademas de esperar a que finalice la conversion
Ser Colombiano es un Premio, Saludos desde CALI-COLOMBIA

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: Problema con #int_AD
« Respuesta #6 en: 20 de Diciembre de 2009, 16:21:31 »
De uno depende darle 20us al capacitor sample&hold para que copie el voltaje instantáneo de la señal.

Después uno arranca la conversión levantando el bit que pone jhozate. Es ahí cuando uno puede hacer 2 cosas:

- Esperar a que el bit go/done baje en un ciclo con polling, que es lo que hace read_adc de CCS
- O irnos a hacer otras cosas, procesar demás asuntos y ser interrumpidos por int_ad cuando go/done cambie de estado

Considerando que la conversión adc es muy rápida lo mejor es usar read_adc ya que la espera es muy breve.

Pero debe quedar claro que los 20us son antes de arrancar la conversión y no son el tiempo que dura la conversión.

Int_ad puede resultar útil cuando el reloj interno del adc es muy lento y se puede aprovechar que el adc está convirtiendo para hacer otras cosas mientras tanto.

Desconectado gera

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2188
Re: Problema con #int_AD
« Respuesta #7 en: 20 de Diciembre de 2009, 16:48:31 »

rea_adc();
traduce el siguiente assembler
Código: [Seleccionar]
009A:  BSF    1F.2    //poner a uno el bit go/done, es decir  inicializar la conversion
009B:  BTFSC  1F.2  //he aqui donde se queda infinitamente
009C:  GOTO   09B  //esperando a que se ponga a cero el bit go/done
009D:  MOVF   1E,W //lectura del registro adresh

read_adc se encarga de iniciar el conversor y ademas de esperar a que finalice la conversion

No tenia idea q existia eso jeje. Gracias por el dato jhozate!! :D

"conozco dos cosas infinitas: el universo y la estupidez humana. Y no estoy muy seguro del primero." A.Einstein

Desconectado jhozate

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1698
Re: Problema con #int_AD
« Respuesta #8 en: 20 de Diciembre de 2009, 17:11:49 »
entonces, se puede concluir que no vale la pena usar la int_ad, a no ser que se use reloj interno??
Ser Colombiano es un Premio, Saludos desde CALI-COLOMBIA

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: Problema con #int_AD
« Respuesta #9 en: 20 de Diciembre de 2009, 17:26:41 »
Si el reloj es muy lento es recomendable usarla. Pero como casi siempre usamos el de 1/32 pues no creo... nunca he medido el tiempo que tarda una conversión ADC, sería bueno simularlo e Proteus o medirlo por software.

Edito: podría medirse con proteus así:

Código: [Seleccionar]
output_high(pinb0);
read_adc();
output_low(pinbo);

y en el osciloscopio checar el tiempo de la patita.
« Última modificación: 20 de Diciembre de 2009, 17:48:51 por migsantiago »

Desconectado iNoXSteeL

  • PIC12
  • **
  • Mensajes: 75
    • La web de InoX
Re: Problema con #int_AD
« Respuesta #10 en: 20 de Diciembre de 2009, 18:08:20 »
Gracias por las respuestas,

Entonce casi que me olvido de la interrupción, había pensado meter la conversión dentro un timer y que el se encargue de actualizar las variables sin tener que recurrir a llamar a la función de lectura.

Probaré así.

Un saludo   8)

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Problema con #int_AD
« Respuesta #11 en: 20 de Diciembre de 2009, 18:30:02 »
Hay varias cosas que le están errando, primero que nada tener en cuenta los 20us para cargar el capacitor de sample&hold es para los PIC de la familia 16F, los 18F podemos configurar para que el tiempo de adquisición se realice automáticamente dependiendo del reloj de conversión, y el mínimo a esperar debe ser de 2.5 us.

La configuración del reloj de conversión también es importante, ya que no puede ser menor a 0.7us en un 18F, y como se utilizan 11TAD es sencillo determinar cuanto tiempo demora la conversión

Respecto a la interrupción creería que la forma correcta sería colocar read_adc(read_adc(ADC_START_ONLY); para iniciar la conversión, y en la interrupción capturar el valor con:
value=read_adc(ADC_READ_ONLY);


Saludos!
No contesto mensajes privados, las consultas en el foro


 

anything