Valor del ADC con PIC16F877A mostrado en LEDs

Buenas tardes gente, he buscado a lo largo del foro y siempre he encontrado este tema pero con visualización en LCD. En mi caso, yo quiero hacer la visualización en leds. Para tal motivo, escribí el siguiente código en CCS C Compiler.

Código:
#device adc=8
void main()
{  
   setup_adc(adc_clock_div_32);
   setup_adc_ports(all_analog);
   set_adc_channel(0);
   set_tris_c(0);
   int8 valor_adc;

   while(true)
   {
      delay_us(20);
      valor_adc = read_adc();
      output_c(valor_adc);
   }

}

Escogí la división entre 32 porque estoy trabajando con un cristal de 20MHz. En ese sentido Tad = 32Tosc = 32/20MHz = 1,6us y 12Tad aproximadamente 20us. Al simular el Proteus me arroja el siguiente warning:

Código:
ADC conversion started before \'wait\' time has expired following previous conversion or channel change

Entiendo por esto que el delay es muy corto, pero ¿por qué?. Más allá de sintaxis de código necesito que me ayuden a entender el tiempo de adquisición y como calcularlo correctamente de acuerdo a la división de reloj que utilice (siempre trabajo con 20MHz). Además ¿qué ventajas tiene usar el reloj RC interno del PIC? y ¿cómo cambia el código si decido usar los 10 bits de conversión?

Espero que me puedan ayudar, muchas gracias de antemano. ...
 
Más allá de sintaxis de código necesito que me ayuden a entender el tiempo de adquisición y como calcularlo correctamente de acuerdo a la división de reloj que utilice.(siempre trabajo con 20MHz)
Esos datos están bien explicados en la hoja de datos. (Incluyendo fórmulas)
Éste tema contiene mucha información que te puede servir:
Conversión: Analógica a Digital & Digital a Analógica
Además ¿qué ventajas tiene usar el reloj RC interno del PIC?
El PIC16F877A no tiene oscilador interno, pero sirve cuando no se requiere usar tiempos precisos en el programa.
Aunque para la mayor parte de aplicaciones, su uso no implica mayores problemas.
Y algunos PIC tienen un oscilador interno que puede llegar más allá de los 32 MHz.
Aparte, su uso da la posibilidad de aumentar dos pines al microcontrolador, ya que se liberan y pueden ser usados como entradas y salidas digitales.
¿Cómo cambia el código si decido usar los 10 bits de conversión?
Eso depende del tipo de programa que estés realizando.
Por ejemplo, en ese programa haces una conversión de 8 bits y el resultado lo puedes enviar a un puerto también de 8 bits, pero con una conversión de 10 bits en donde la lectura máxima es de 1023, ese valor sobrepasará los 8 bits del puerto.
 
La pregunta del millón es: ¿Leiste la hoja de datos con detalle?

TAD (tiempo de conversión) no es igual que TACQ (tiempo de adquisición). En la página 130 de la hoja de datos, ecuación 11-1 ACQUISITION TIME, te menciona cómo calcular el tiempo para que el capacitor CHOLD se cargue correctamente, PERO en la página 195, tabla 17-15 A/D CONVERSION REQUIREMENTS, el fabricante te recomienda utilizar 40us. Generalmente yo utilizó lo doble que recomienda el fabricante.

El tiempo de conversión necesarios para convertir la señal analogica (voltaje del capacitor CHOLD ) a una señal digital de 10 bits es de 12 TAD's. Como tu estas utilizando un prescaler de 32Tosc y un oscilador de 20MHz, tienes un TAD = 1.6us (lo mínimo que permite la conversión para obtener una buena lectura). Tu conversión dura aproximadamente 20us (sin tomar en cuenta otras variables). Utilizar TAD = RC interno, como varía entre 4us ~ 6us tendrías en teoría una conversión más exacta.

Después el valor de 10 bits se divide entre los registros ADRESH (8 bits) y ADRESL (8 bits). Pero dependiendo del formato seleccionado (Justificado a la derecha o Justificado a la izquierda) del registro ADCON1 (bit 7, ADFM) deberás hacer la suma de los registros para obtener un número de 16 bits, igual a una variables INT (65536). Para más información ve la figura 11-4 (página 132 de la hoja de datos).

Un ejemplo sería el siguiente (en mikroC):

Código:
unsigned int resultado = 0; //variable de 16 bits (n = 65535)

void main() {
TRISA = 0b00000001; //RA0 config. como entrada,
TRISC = 0b00000000; //Puerto C config. como salidas,
TRISD = 0b00000000; //Puerto D config. como salidas,

ADCON0 = 0b10000000; //Tiempo de conversión de 32Tosc,
ADCON1 = 0b10001110; //RA0 config. como entrada analogica,
                     //Justificado a la derecha,
                     
PORTA = PORTC = PORTD = 0; //Puertos A, C y D inician en cero,

while(1) {
ADON_bit = 1; //Conversión A/D hablitada,
delay_us(80); //tiempo de adquisición (TACQ),
  GO_bit = 1; //Inicia conversión A/D,
while(GO_bit == 1) //espera que termine la conversión (12*TAD)...
                   //bit GO/DONE se pone a cero automaticamente,

resultado = (ADRESH << 8) + ADRESL; //resultado de 10 bits (n = 1023),

PORTC = resultado;
PORTD = resultado >> 8;
 
Última edición:
A los dos, muchísimas gracias, leyéndolos ya tengo una mejor idea de lo que está pasando en el código. Seguiré indagando y leeré el datasheet con detalle y lupa si es necesario. Muchas gracias, de verdad!
 
Atrás
Arriba