Ayuda con conversor A2D en C de Hi-Tech

Hola foreros, en esta ocasión ando necesitando información para realizar un conversor analógico a digital para registrar la temperatura de un LM35 en un pic 18f452. Eh leido el ejemplo que trae el compilador y algunos otros en la web, pero no termino de comprenderlo.
Necesito registrar la temperatura y transferirla a un lcd, lo cual no es problema.
Si alguien me puede ayudar con el codigo, o mejor, ayudarme a comprenderlo y asi poder hacer andar correctamente el A2D se lo agradeceria mucho.

Muchas Gracias
Gonzalo

PD: Como puedo enviar el valor de una variable al lcd?

yo escribo por ejemplo:
int x=4;

lcs_puts(x);

y me escribe cualquier cosa. Espero haberme hecho entender. Saludos y gracias
 
Muestra el código que estás usando para configurar el A2D del PIC, que seria lo más importante.
o mejor el ejemplo que estas usando y así comprender que está haciendo...
Te recuerdo que el C de Hi-Tech es ANSI C es casi en su totalidad compatible con el C18 del MPLAB y tiene algunas cosas que confunden a la primera; por eso postea el ejemplo.

Un saludo
 
muchas gracias por responder. Aca subo el ejemplo que trae el compilador. Lo dejo adjuntado. Esta el .c el .h y un txt que explica que hace mas o menos.
Espero que me puedan ayudar
Muchas gracias por su tiempo
Saludos
Gonzalo
 

Adjuntos

  • a2demo.c.txt
    2 KB · Visitas: 35
  • a2demo.h.txt
    168 bytes · Visitas: 19
  • a2demo.txt
    1.5 KB · Visitas: 20
Te paso el código del ejemplo, le puse algunos comentarios en algunas partes del código
y también te adjunto un ejemplo que lee en RA0 del PIC18F452 a 4Mhz...

Otros detalles con respecto a tu ejemplo es que configures bien la frecuencia del oscilador
de lo contrario vas a tener varios problemas...

Sobre el LM35 ya hay info en el foro:
https://www.forosdeelectronica.com/f24/escalar-lm35-temperatura-microcontrolador-18331/

Si tienes dudas con el compilador me avisas.

Saludos
 

Adjuntos

  • EjemploA2D.txt
    2.7 KB · Visitas: 41
  • a2demo.c.txt
    2.5 KB · Visitas: 29
Carlos Alexis muchas gracias por tu ayuda, ahora creo que voy entendiendo un poco como funciona esto.
A pesar de todo, me han surgido algunas nuevas dudas, que espero que me puedas resolver si no es mucho pedir.

1: El resultado de tu ejemplo (ValueADC = (ADRESH<<8)+ADRESL) esta en binario, o automáticamente se convierte a decimal?

2: No termino de entedder el desplazamiento hacia la izquierda ADRESH<<8. Es necesario esto?

3: Yo quiero mostrar el valor de la temperatura en un lcd.
Lo que hice para convertir el valor ValueADC a grados centrigrados fue:

temp = ValueADC / 2.048; (temp es un unsigned int)

Esta bien la operacion de convercion? la saque del link que me pasaste.
EDITADO: si la forma en que intento mostrar el resultado en el lcd y todo el resto es correcto, esta operacion es incorrecta por que los valores no concuerdan con la temperatura. Cual seria la operacion correcta?

4: Como muestro el valor de temp en el lcd?
para convertir el valor en string para mostrarlo por el lcd, estoy haciendo lo siguiente:

char temp1[4];
...
...
...
temp = ValueADC;
sprintf(temp1,"%4.1f", temp);
lcd_puts(temp1);

Muchas gracias
Saludos
Gonzalo

PD: Anado el codigo entero:

/* El ejemplo lee el canal RA0 */
/* Resolución a 10bits */
#include <htc.h>
#include <stdio.h>
#include "lcdportD.c"
#include "delay.c"

__CONFIG(1,XT & OSCEN);
__CONFIG(2,PWRTDIS & WDTDIS);
__CONFIG(4,DEBUGDIS & LVPDIS);
__CONFIG(5,UNPROTECT);
__CONFIG(7,SWDTDIS);

unsigned int ValorAnterior;
unsigned int ValueADC;
void init(void);
void
main(void)
{
lcd_init(0);
lcd_puts("System Up");
float temp;
char temp1[4];


init(); // Inicia registros
DelayBigMs(500);
lcd_clear();
while(1){

lcd_puts("Nueva muestra");
DelayBigMs(300);
lcd_clear();

GODONE = 1; // Inicia conversión

while(GODONE); // Espera a fin de converción
ValueADC = 0;

ValueADC = (ADRESH<<8)+ADRESL; // Reune el valor en una varible
//printf("%u\r", ValueADC); // Imprime el valor

temp = ValueADC*2.048;
sprintf(temp1,"%4.1f", temp);
lcd_puts(temp1);

DelayBigMs(450);
lcd_clear();



}

}

//-----------------------
/* Se ha usado el C-Wiz del HiTech para configurar */
/* el PIC y el código resultante es: */

void init(void){
/***** Common Code ****
* Usart1TX interrupt disabled
* Usart1RX interrupt disabled
* A2D Converter interrupt is disabled
*/
/*
* Port directions: 1=input, 0=output
* Bit 6 Configured for Usart1 TX
* Bit 7 Configured for Usart1 RX
*/

TRISA = 0b00000001;
/*
* Port directions: 1=input, 0=output
*/

/***** A2D Converter Code ****
* A2D Converter is enabled
* A2D status is idle
* Analog Channel is AN0
* Conversion Clock (Internal RC Oscillator)
*/
ADCON0 = 0b11000001;
/*
* Analog/Digital ports using configuration 14
* Conversion Clock (Internal RC Oscillator)
* A2D Converter is Right Justified
*/
ADCON1 = 0b10000000; //ADCON1 = 0b10001110; este es el original
/*
* Right Justified
*/
ADRESH = 0b00000000;
}
 
Última edición:
1ro: No confundamos que el valor en una variable por ejemplo de 8 bits, ya sea representado en binario, hexadecimal, decimal, octal... siempre es el mismo valor que cave en esa variable de
8 bits. Solo son representaciones, pero a la hora de mostrar el valor a un lenguaje conocido que una persona visualmente conozca es necesario convertir y el más usado es el ascii, que cada carácter (letras, números y símbolos) ocupa 8 bits.

1: El resultado de tu ejemplo (ValueADC = (ADRESH<<8)+ADRESL esta en binario, o automáticamente se convierte a decimal?
2do: En (ADRESH<<8)+ADRESL; lo único que hace es unir los registros ADRESH y ADRESL (que son de 8 bits') en una sola variable de 16bits manteniendo el valor del ADC ya que la resolución es a 10bits. Por eso se pone los 2 bits más altos del ADC (ADRESH) en la parte más alta de la variable ValueADC (8bits más altos) y luego se le agrega ADRESL en los 8 bits más bajos de ValueADC. El valor sigue sin modificaciones pero al estar en una sola variable, es más cómodo de usar el valor a 10bits.

2: No termino de entedder el desplazamiento hacia la izquierda ADRESH<<8. Es necesario esto?
3ro) Si solo insiera ValueADC = ADRESH;... sucede que el valor de ADRESH solo se coloca en los 8 bits más bajos de la variable y como lo que se quiere es ponerlo en los 8bits más altos entonces se desplaza los 8bits de ADRESH hasta que ocupe los 8bits más altos de la variable.

4: Como muestro el valor de temp en el lcd?
Tendria que convertirlo a string no es cierto?
4to) Si.

Tienes cierta ventaja en comodidad si usas printf y te evitas aveces d engorrosas convenciones ya que, por ejemplo al usar printf("%d\r", ADRESL); y en la función void putch(char d); agregas código para que el dato lo mande vía RS232 entonces estará imprimiendo el valor de ADRESL en string representado en decimal.
Ahí mismo dentro de la función void putch(char d); puedes agregar código para que el dato que entre por (char d) lo envíes al LCD, además no hay problema porque en la variable "d" ya estará un carácter resultado de la conversión en string que realizo printf();

Saludos...
 
Carlos Alexis, ya lo pude hacer funcionar, muchas gracias por tu ayuda.

No termino de comprender lo de ADRESH<<8
En ADRESH se guardan los 8 bits mas significativos del resultado y en ADRESL los 8 bit menos significativos.

Por lo que estuve leyendo de la configuracion de ADCON1=0b10000001, el primer digito decide el tipo de justificacion:
1 = Right justified. Six (6) Most Significant bits of ADRESH are read as ’0’.
0 = Left justified. Six (6) Least Significant bits of ADRESL are read as ’0’.

Preguntas:
1) Si lo tengo en 1, se borran los 6 bits mas significativos. No estoy perdiendo informacion de esta forma? No seria mejor que borrara los 6 menos significativos del ADRESL?

2)No seria conveniente que el resultado estuviese formado por los 8 bits mas significativos del ADRESH y los 2 bits mas significativos del ADRESL\

3)Por que si el ADC tiene una resolucion de 10bit, guarda el resultado en dos variables de 8 bits, osea 16 en total?

Bueno, por ahora eso es todo, disculpa que sea tan molesto, es que soy medio duro y no termino de comprender.
Muchas gracias
Gonzalo
 
Atrás
Arriba