ADC con PIC 18F13K50

Buenas noches,

he estado jugando con el modulo ADC de este PIC, pero no consigo hacerlo andar.

Proteus me indica que no tengo configurado el pin como entrada analogica, y que intento hacer una conversion AD sin haber dado tiempo a terminar la anterior.

Soy completamente nuevo en el tema de la conversión AD, y más aún con estos PICs mas "sofisticados". Por ello me he basado en un ejemplo ya hecho para enviar los datos por el USB.

Pego el codigo a continuación:
Código:
#include <18F13K50.h>

#device adc=10
#fuses NOWDT,NOLVP,NODEBUG,USBDIV1,CPUDIV1
#use delay(clock=48000000)

#define USB_HID_DEVICE     FALSE             //deshabilitamos el uso de las directivas HID
#define USB_EP1_TX_ENABLE  USB_ENABLE_BULK   //turn on EP1(EndPoint1) for IN bulk/interrupt transfers
#define USB_EP1_RX_ENABLE  USB_ENABLE_BULK   //turn on EP1(EndPoint1) for OUT bulk/interrupt transfers
#define USB_EP1_TX_SIZE    1                 //size to allocate for the tx endpoint 1 buffer
#define USB_EP1_RX_SIZE    3                 //size to allocate for the rx endpoint 1 buffer

#include <pic18_usb.h>                          //Microchip PIC18Fxx5x Hardware layer for CCS's PIC USB driver
#include "usb_desc_scope.h"                  //Configuración del USB por Enumerador Palitroquez
#include <usb.c>                                //handles usb setup tokens and get descriptor reports

#define LED PIN_B7

unsigned int16 valor_adc;

int8 recibe[1];
int8 envia[1];

void main(void)
{
    set_tris_b(0);                               //SALIDA
    set_tris_a(255);                             //ENTRADA
    set_tris_c(255);                             //ENTRADA

    usb_init();                                    //inicializamos el USB
    usb_task();                                     //habilita periferico usb e interrupciones
    usb_wait_for_enumeration();                     //esperamos hasta que el PicUSB sea configurado por el host

    #asm

        //Configuro el ADCON1:

        bcf 0xFC1,3            //Se toma Vref+ del pin correspondiente
        bsf 0xFC1,2
        bcf 0xFC1,1            //Se toma Vss para Vref-
        bcf 0xFC1,0

        //Configuro l'ADCON0:

        bcf 0xFC2,7
        bcf 0xFC2,6
        bcf 0xFC2,5
        bsf 0xFC2,4
        bsf 0xFC2,3
        bsf 0xFC2,2
        bsf 0xFC2,0
        
        //Configuro l'ADCON2:

        bcf 0xFC0,7        //Justificación a la derecha
        bsf 0xFC0,5        //Tiempo de asquisición 12TAD
        bcf 0xFC0,4
        bsf 0xFC0,3
        //bcf 0xFC0,2    //No compredo bien que debe ir aquí
        //bcf 0xFC0,1
        //bcf 0xFC0,0

    #endasm

delay_us(20);

   while (1)
   {
          if(usb_enumerated())                      //si el PicUSB está configurado
          {
            if (usb_kbhit(1))                     //si el endpoint de salida contiene datos del host
             {
                output_high(LED);                //Se enciende el LED

                usb_get_packet(1, recibe, 2);

                if(recibe[0]==0x01)
                {
                    envia[0] = 10;
                    usb_put_packet(1, envia, 1, USB_DTS_TOGGLE);    //Si hay comunicación, envio un '10'
                }

                if(recibe[0]==0x02)
                {
                       valor_adc=read_adc ();                         //Hace conversión AD
                    delay_us(20);                                //Esperamos a que termine

                    envia[0]=make8(valor_adc,1);                     //Seleccionamos el valor alto
                    usb_put_packet(1, envia, 1, USB_DTS_TOGGLE);
                }

                if(recibe[0]==0x03)
                {
                    envia[0]=make8(valor_adc,0);                     //Seleccionamos el valor bajo
                    usb_put_packet(1, envia, 1, USB_DTS_TOGGLE);
                }

                if(recibe[0]==0x04)
                {

                }
                if(recibe[0]==0x05)
                {

                }

             }

          }

    }
}

Agradezco cualquier consejo. Por cierto, no termino de entender el tema de la TACQ. Pero vamos paso a paso..

Lo curioso es que, basandome en el mismo ejemplo, y con una version de CCS anterior pude simular perfectamente un programa casi identico con el PIC18F2550...
 
Vamos a ver. Yo sigo a lo mio.

Entiendo que en el uso del conversor AD se debe empezar por configurar los registros ADCONX. Verdad?

En primer lugar, ADCON0, que contiene los bits correspondientes al canal de entrada, la activacion, o no, del conversor, etc.

Por otro lado, el registro ADCON1, cuyos bits sirven para configurar la justificacion, la Vref+, y la Vref-.

Y despues el ADCON2, para definir el Tad, el Tacq, y no recuerdo que mas (escribo desde el metro).

Las opciones que proporciona CCS para configurar estos parametros no me han parecido demasiado claras, por ese motivo he optado por configurar los bits en assembler. Pero no deberia afectar en nada, no?

Por otro lado, el tema del Tad y el Tacq, no me quedan demasiado claros. Entiendo que el primero es el tiempo que el PIC necesita para hacer la conversion, y el otro el tiempo que tarda en adquirir los datos, y que esta relacionado con la carga del condensador que hay en el modulo AD.

Tacq, segun el datasheet, para unos valores de Vcc=3V y temp=50C es de 7,5 us. De momento, para la simulacion, me quedo con este valor.

Pero no termino de entender como debo configurar el Tad. Algun consejo, pagina donde mirar, etc?

Hechas todas estas configuraciones y calculos, entiendo que no debo generar retardos por software, ya que ya he indicado los tiempos del AD, no?

Gracias por adelantado!
 
SOLUCIONADO (pero no tengo claro como)

Por lo visto, el CCS no escribe correctamente el registro ADCON0. En concreto, no escribe cual de las entradas analogicas debe leer.

Para encontrar el fallo he escrito otro programa que solamente observa la entrada y enciende un led, si su valor esta por encima de la mitad de Vcc, y lo mantiene apagado en caso contrario.

el codigo es este:

Código:
#include <18F13K50.h>

#device adc=8
#fuses NOWDT,NOLVP,NODEBUG,USBDIV1,CPUDIV1
#use delay(clock=48000000)

#define LED PIN_C7

int valor_adc;

void main(void)
{
    //Entrada por PORTA, y salida por PORTC
    set_tris_a(0xFF);
    set_tris_c(0x00);

    //Configuramos el conversor AD:
    setup_adc_ports(sAN3);

    #asm           //Vuelvo a configurar la misma entrada analogica, pero esta vez en assembler
    bcf 0xFC2,5
    bcf 0xFC2,4
    bsf 0xFC2,3
    bsf 0xFC2,2
    #endasm

    setup_adc(ADC_CLOCK_INTERNAL);
    
   while (1)
   {
        valor_adc=read_adc();                         //Hace conversión AD

        if(valor_adc >= 128) output_high(LED);        //Si la lectura, supera cierto nivel, se enciende un LED
        else output_low(LED);                        //Si no, se apaga

        delay_us(20);                                //Esperamos 20us para volver a empezar.
    }
}
El procedimiento ha sido el siguiente: tras configurar la entrada analogica (sAN3), he estado observando el comportamiento del registro ADCON0, y he observado que nada variaba tras ejecutarse esta instrucción.

Por ello he procedido a configurar los bits correspondientes a la entrada analogica que deseo usar en assembler. Pero mi sorpresa ha sido, que si elimino la sentencia de configuración de CCS (setup_adc_ports(sAN3)) tampoco funciona. Solamente manteniendo las dos sentencias de configuración, la de CCS, y en assembler, el programa funciona sin problemas.

Alguien me puede ayudar a descifrar el misterio?

Muchas gracias!
 
Última edición:
Atrás
Arriba