# Adc 8 bits + eeprom ext  I2C + Rs232 al Pc con PIC16F873 CCS



## sebaelkan (Sep 29, 2008)

Hola a todos! Tengo unos cuantos problemas programando en CCS.
He de coger una señal analogica por el puerto A0, configurado con set_tris_a (...), pero luego con el read_adc() para ponerlo en una variable, no se como enfocarlo.

he visto cosas del estilo valor=read_adc(); con algun bucle para que vaya cogiendo valores. Tengo que hacer unos 16000 samples de 8 bits ( a lo mejor he de hacer un for o do_while de 0 a 16000?), y pasarlos despues auna eeprom externa de 8 x 16000 = 128Kbits diria, para que me guarde todos los datos...

Tambien hay un tema de retardos (adc, r/w eeprom, buffers), definicion de #rom...

No se si he de hacer funciones por separado, o todo dentro del main()

Desde ya mismo, gracias por vuestra ayuda, porque la necesito urgente! Se q son muchos bloques por separado y despues de saber como hacerlos, he de encajar todos los bloques en conjunto.

Gracias!


----------



## Moyano Jonathan (Sep 29, 2008)

como andas , mira lo que queres hacer es un datalogger segun veo pero en vez de hacer 16000 samples con un bucle for podrias tomar una muestra cada cierto tiempo por ejemplo cada 2 a 4 segundos y guardar el resulatdo en una eeprom externa


----------



## sebaelkan (Sep 29, 2008)

Tengo que tomar minimo 1000 muestras por segundo, o sea frec de muestreo = 1KHz.

Primero que el ADC interno de 10 bits, se puede configurar a 8 bits y su frec muestreo minima es de 1,25 MHz.

Pondre algo de codigo a ver si voy bien encaminado. Gracias...


//Codigo del ADC como programa, no como funcion a llamar desde el main//

#include <16f873.h>
#device ADC=8   // ADC devuelven 8 bits
#fuses NOPROTECT,NOCPD,NOLVP,NOWDT,XT //Configuracion de timers, reloj, proteccion de datos...


#use fast_io (A)   //Input y output sin reprogramar los pines, como lo haria el #use standard_io
#use fast_io (B)
#use delay(clock=4000000) //Reloj de 4MHz

int8 resultado;      //Variable para el resultado de la conversión AD

main() //main o void main()?
{  

   //Se activa el ADC y se selecciona el canal RA0/AN0. Frecuencia de trabajo Fosc/32

   setup_adc(adc_clock_div_32);   //Ajusta frecuencia de muestreo del ADC

   while(input(PIN_A1)) // Cuando pulse el boton...(activo por 1)
   {
      delay_ms(10000); // Esperar 10 segundos para encender el cohete

      while(1)
      {   
         setup_adc_ports(AN0);    //RA0 entrada analógica
         set_adc_channel(0);      //Selección del canal 0 (RA0)
         delay_us(10);            //Temporiza 10uS
         resultado=read_adc();    //Inicia la conversión y lee el resultado
      }
   }
}


----------



## sebaelkan (Sep 29, 2008)

//Funcion de interrupcion de eeprom:ejemplo


#int_eeprom

void interrupt_service_rutine_eeprom(void) 
{
   flag_Writing_INTERNAL_EEPROM=0;
}

void writeByteINTEEPROM(int8 memAddress, int8 data)     //funcion de escritura y puesta de flags para escribir Byte de dato
{  

   flag_Writing_INTERNAL_EEPROM=1;
   enable_interrupts(int_eeprom);
   write_eeprom (memAddress, data);

   while(flag_Writing_INTERNAL_EEPROM==1){/*Wait for write finish*/}
   disable_interrupts(int_eeprom);
}


//Funciones  read_eeprom(address) y  write_eeprom(address, byte) para datos de 16 bits, aunque yo utilizare //de 8 bits

void write_eeprom_16bits(int address, long* val){

  int pLow, pHigh;
  pLow = val;
  pHigh = val>>8;
  write_eeprom(address,pHigh);
  delay_ms(12);
  ++address;
  write_eeprom(address,plow);
  delay_ms(12);
}

long read_eeprom_16bits(int address){

  int pLow, pHigh;
  long result;
  pHigh = read_eeprom(address);
  ++address;
  pLow = read_eeprom(address);
  result=(pHigh<<8);
  result+=pLow;
  return result;


//Pongo todos los codigos a los cuales he podido llegar mas o menos, pero en ningun caso los he probado ni //se como encajar las fichas del puzzle


----------



## sebaelkan (Sep 29, 2008)

#use fast_io (B)
#use fast_io (C)

#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#int_rda   //Vector de interrupción al recibir por el UART

//Función de tratamiento de la interrupción al recibir

tratamiento()
{   
   int   dato;   //Variable para almacena el dato recibido
   dato=getc();   //Lee el dato recibido
   output_b(dato);   //Lo saca por la puerta B
   putc(dato);      //Lo transmite vía RS232   
}   

main()
{     
   output_b(0x00);              //Borra las salidas
   set_tris_b(0x00);            //Puerta B salida
   set_tris_c(0b10111111);      //RC7/Rx entrada, RC6/Tx salida
   enable_interrupts(INT_RDA);  //Activa interrupción en la recepción
   enable_interrupts(global);   //Habilita interrupciones

   while(1)
   {   

   }

// Solo envio de datos, sin ningun tipo de interrupcion.

main()
{     
   set_tris_c(0b10111111);   //RC7/Rx entrada, RC6/Tx salida

   while(1)
   {   
      putc('A');      //Transmite el caracter
      delay_ms(1000);   //Temporiza 1 segundo
   }
}


Desde ya muchas gracias!


----------



## Moyano Jonathan (Sep 29, 2008)

Vos decis que tenes que tomar 1000 muestras por segundo , pero cada vez que el adc toma un valor la variable resultado cambia por lo que solo te puede almacenar un valor por vez en la memoria eeprom y ademas tarda aproximadamente 10ms guardar cada dato en (asm) por lo que en 1 seg podrías guardar 100 valores max .

Otra cosa que me parece que tendrías que tener en cuenta es el tiempo que le toma al adc realizar la conversión del dato analógico al digital. eso lo dice en la hoja de datos . entonces dividis 1 seg por el tiempo de conversion y te a dar la cantidad de veces que se puede leer el adc en 1 seg.

Cualquier cosa que este metiendo la pata decime en caso contrario , espero que te ayude


----------



## witchblade (Mar 31, 2009)

yo tengo un problema algo similar, usando un  16f87x necesito tomar el dato analogo cada 20s e irlo almacenando para que al paso de 4 minutos (12 datos almacenados) sacar un promedio de los datos almacenados, la verdad soy nuevo en este cuento de los pics, se me habia ocurrido segun lo que he leido en no almacenar cada dato leido en una variabel diferente sino ir sumando al anterior el dato nuevo que se lea y despues divir esto por 12 para sacar el valor promedio y despues si mostrar este en la salida ya digitalizado.

Si alguien me puede dar luces al respecto les agradeceria mucho.


----------



## karl87 (Nov 24, 2009)

hola yo estoy unsando un pic18f4553, y deseo realizar el muestreo de una señal de 2kh de frcuencia,, pero al implementarlo en mi pic, no logro visualizarla correctamente en mi PC, estoy usando una comunicacion USB,, grax espero me ayuden


----------

