Autor Tema: Uso del adc en la serie 18F configurando el tiempo de adquisicion  (Leído 3832 veces)

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

Desconectado kain589

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 324
Saludos! Abro este hilo por si a alguien le puede servir de ayuda, estaba haciendo un programa que envia por el puerto serie el valor del adc cada vez que le enviamos un caracter, esto es mas que nada para poder comprobar valores sin que el monitor serie se nos llene de datos como podria pasar si enviamos el valor cada segundo por ejemplo.

En este caso usaba el adc con 8 bits de definicion, era solo una prueba y es una forma de disminuir los efectos del ruido. El pic usado es el 18f2550.

Pues bien, el programa iba bastante mal: los datos oscilaban sin modificar el potenciometro, a veces eran oscilaciones demasiado grandes, y lo mas raro venia cuando estaba al maximo voltaje en lugar de 255 o un valor cercano, me marcaba 15, a veces 31 y alguna suelta 63; curioso que los datos sean igual a multiplicar el anterior por 2 y sumar uno.

La solución la he encontrado al modificar el tiempo de adquisición para el conversor, el conversor en los pic18f no es igual a la serie pic16f, en la serie 18f nos permite por "hardware" establecer un tiempo de espera para que se estabilice el conversor, y ese tiempo es el tiempo de adquisicion de datos.

Este tiempo se puede configurar mediante los bits ACQT2:ACQT0 que se encuentran en el registro ADCON2, en el datasheet se puede observar en la pagina 257.

ACQT2:ACQT0: A/D Acquisition Time Select bits
111 = 20 TAD
110 = 16 TAD
101 = 12 TAD
100 = 8 TAD
011 = 6 TAD
010 = 4 TAD
001 = 2 TAD
000 = 0 TAD

El "problema" es que no hay una forma directa de establecer este tiempo con el CCS, o yo no la conozco. La solucíon ha sido definir el registro usando la directiva:

#byte ADCON2=0xFC0

Y posteriormente aplicando mascaras para poner a 1 o a 0, los bits que deseamos del registro. En mi caso uso un tiempo de 20 Tad, con lo que hay que poner a 1 los tres bits:

ADCON2= ADCON2 | 0b00111000;

Si se deseara caragar en los bits el valor "101" por ejemplo, posteriormente habria que hacer una and para poner a 0 los bits deseados:

ADCON2= ADCON2 | 0b00101000;

ADCON2= ADCON2 & 0b11101111;

Consiste en aplicar mascaras de forma que modifiquen los bits que deseamos:

- Para poner a 1, se usa la operacion "or" (|)con una mascara que contengan con bits a 1 aquellos que deseamos setear(poner a 1) y los demas a 0 para no modificar el resto del registro.

- Para poner a 0, se usa la operacion "and"(&) con una mascara que contengan con bits a 0 aquellos que deseamos limpiar(poner a 0) y los demas a 1 para no modificar el resto del registro.

Código: C
  1. #include <18F2550.h>
  2. #device ADC = 8
  3. #fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL3,CPUDIV1,VREGEN
  4. #use delay(clock=48000000)
  5. //Configura comunicacion serie
  6. #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
  7. //#byte nombre=direccion
  8. //se define byte control adcon2, controla t.adquisicion, justificacion y reloj
  9. #byte ADCON2=0xFC0
  10. char Keypress=' ';
  11. int8 valor;
  12.  
  13. #int_rda
  14. void serial_isr() {
  15.  
  16.   Keypress=0x00;
  17.   if(kbhit())
  18.    {
  19.     Keypress=getc();
  20.     if(Keypress!=0x00)
  21.       {
  22.       valor=read_adc(ADC_START_AND_READ);//Inicia conversion y lee, hara espera automatica
  23.       delay_ms(1);
  24.       printf("\n\rEl valor del adc es : %u",valor);//muestra dato mayor
  25.       }
  26.    }
  27. }
  28.  
  29. void main()
  30. {  //Establecer a como entrada
  31.    set_tris_a(0x01); //Entrada an0
  32.    //Se define entradas analogicas y valores referencia
  33.    setup_adc (adc_clock_div_64); //Enciende ADC, pongo 64 en lugar 32 a ver si mejora
  34.    //se configura t.adquisicion sin modificar demas, se usa operacion or
  35.    //se usara tadq de 20 tad, bits acqt2..0 todos a 1
  36.    //para poner a 0 se utilizaria and con 0 en bit a modificar y demas a 1
  37.    ADCON2= ADCON2 | 0b00111000;
  38.    setup_adc_ports (AN0_ANALOG); //Elige entrada analogica
  39.    set_adc_channel (0); //Elige canal a medir
  40.    //Habilita interrupcion rda
  41.    enable_interrupts(global);
  42.    enable_interrupts(int_rda);
  43.  
  44.    printf("\r\n\ Conectado \r\n");
  45.  
  46.   do {
  47.       } while (TRUE);
  48. }

No sé si a alguien mas le ha dado problemas, a mi bastantes por lo que he puesto aqui la solución por si a alguien mas le puede servir.
Saludos desde Córdoba, españa

Desconectado micro_cadaver

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2102
    • blog microembebidos
Re: Uso del adc en la serie 18F configurando el tiempo de adquisicion
« Respuesta #1 en: 15 de Abril de 2009, 18:02:31 »
 :-/ :-/ gracias po tu aporte,... sos groso sabelooooooooooo  :mrgreen:

estoy seguro le ayudara a muchos otros que se han topado con dicha dificultad.  :-)
a cosechar!!!... :P
pic32... ahi voy....
aguante el micro 16f84  !!!!

visita mi pagina: http://www.microembebidos.wordpress.com