Autor Tema: Duda sobre conversor ad del pic 16f877a  (Leído 2766 veces)

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

Desconectado yeestrada

  • PIC10
  • *
  • Mensajes: 15
Duda sobre conversor ad del pic 16f877a
« en: 27 de Abril de 2011, 11:37:14 »
Hola a todos, estoy tratando de leer  del conversor ad del pic 16f877a, todo es muy simple, pero que sucede,cuando realizo la lectura me da un valor entre 0 y 255 (8bit) y lo que necesito es obtener los 2bytes que lee (10 bit) o al menos eso es lo que dice en el datasheet, a ver si pueden ayudarme a obtener los 2bytes en vez de 1 solo para poder guardar la medición lo más exacta posible... esto es lo que tengo hecho:    :)

#include <16F877A.h>                ///   libreria para el manejo del pic16f877a
#include <stdlib.h>
#include "24256.c"
#priority rda,ad,timer1,timer0
#use delay(clock=20000000)          ///   declara  la frecuencia del cristal 20mhz
#use RS232(BAUD=9600,BITS=8,PARITY=N,XMIT=PIN_C6,RCV=PIN_C7)

#use fast_io(A)
#use fast_io(B)
#use fast_io(C)                     ///   con esta instruccion evitamos que
#use fast_io(D)                     ///   se este configurando cada vez que usamos
#use fast_io(E)                     ///   alguna instruccion de entrada o salida

#byte porta = 5
#byte portb = 6
#byte portc = 7                     /// se definen direcciones de memoria
#byte portd = 8
#byte porte = 9

#define EEPROM_SDA PIN_c4
#define EEPROM_SCL PIN_c3

   int nums[7];
   int temporal;
   int cont_letras;                    //variable para contar los 8 numeros que se puede entrar por Tx serie
   int16 time;                           //hasta 300 segundos entre recuperaciones de muestras
   int16 cant_var;                       //hasta 2000 muestras que es necesario recojer
   int cont_seg;
   int16 cont_time;
   int16 cont_var;
   int estado_leds;
   int var_in_rand;
   int lectura_ad;
   int canal_ad;

int Tabla(int a)        //tabla para visualizar numeros por el 7segmentos
{
  switch(a)
  {
      CASE 0:RETURN 0b00111111;
      CASE 1:RETURN 0B00000110;
      CASE 2:RETURN 0B01011011;
      CASE 3:RETURN 0B01001111;
      CASE 4:RETURN 0B01100110;
      CASE 5:RETURN 0B01101101;
      CASE 6:RETURN 0B01111101;
      CASE 7:RETURN 0B00000111;
      CASE 8:RETURN 0B01111111;
      CASE 9:RETURN 0B01100111;
  }
}

int Is_num(int a)
{
   if(a>=48 && a<=57)
    return 0;                          //si es 0 es un numero sino es otro
   return 1;
}

void actualiza_led(int i)
{
   switch(i)
   {
   case 0: portb= 0B11111110;         //PC
           portd= 0B01110011;
           delay_ms(50);
           portb= 0B11111101;
           portd= 0B00111001;
           break;
   case 1: portb= 0B11111110;         //Ad
           portd= 0B01110111;
           delay_ms(50);
           portb= 0B11111101;
           portd= 0B01011110;
           break;
   case 2: portb= 0B11111110;         //Sd
           portd= 0B01101101;
           delay_ms(50);
           portb= 0B11111101;
           portd= 0B01011110;
           break;
   }
}


#use delay(clock=20000000)

void LeerAD(int canal)
{
   lectura_ad = 0;
   setup_port_a( ALL_ANALOG );
   setup_adc( ADC_CLOCK_INTERNAL );
   set_adc_channel(canal);
   lectura_ad = read_adc();
   delay_ms(20);
   setup_adc (adc_off);

}



#int_TIMER0                         //directiva para it del timer0
void TIMER0_isr()
{
    actualiza_led(estado_leds);
    set_timer0(81);
}

#int_rda
void rda_isr()
{
   if(cont_letras < 7)
   {
      temporal = getc();
      if(Is_num(temporal)==0)
      {
         temporal =temporal-48;
         nums[cont_letras] = temporal;
         printf ("%d",nums[cont_letras]);
         cont_letras++;
      }
      else
      {
         cont_letras = 0;
         printf ("Error");
      }
   }
}


void configurar(void)                  //configuraciones
{
   enable_interrupts(INT_TIMER0);         //habilitar el timer0
   enable_interrupts(INT_TIMER1);         //habilitar el timer1
   enable_interrupts(INT_RDA);            //habilitar para comunicación serie
   enable_interrupts(GLOBAL);             //habilitar el bit de it global

   set_tris_d(0x00);
   set_tris_b(0x00);
}


void main()
{
   cont_seg = 0;
   estado_leds = 0;
   cont_letras = 0;
   var_in_rand = 0;
   cont_time = 0;
   canal_ad = 0;
   configurar();
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
   set_timer0(81);
   while(var_in_rand == 0)
   {
      while(cont_letras < 7){}
      cant_var = _mul(nums[0],1000) + _mul(nums[1],100) + _mul(nums[2],10) + nums[3];
      time = _mul(nums[4],100) + _mul(nums[5],10) + nums[6];
      var_in_rand = 1;
      if(time>300 || time<1)
      {
         printf (" Tiempo fuera de rango. ");
         cont_letras = 0;
         var_in_rand = 0;
      }
     else
      if(cant_var>2000)
      {
         printf (" Cantidad de muestras fuera de rango. ");
         cont_letras = 0;
         var_in_rand = 0;
      }
   }
   clear_interrupt(int_rda);
   estado_leds = 1;
   LeerAD(0);
   printf(" %f",lectura_ad);
   while(1){}


}

Desconectado Diego E.

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1086
Re: Duda sobre conversor ad del pic 16f877a
« Respuesta #1 en: 27 de Abril de 2011, 12:00:59 »
Hola amigo, debes declarar la directiva
#device adc = 10

y "int lectura_ad;" debe ser un long

Saludos.

Desconectado yeestrada

  • PIC10
  • *
  • Mensajes: 15
Re: Duda sobre conversor ad del pic 16f877a
« Respuesta #2 en: 27 de Abril de 2011, 12:24:39 »
si, muchas gracias ya lo habia encontrado, sin embargo aún tengo una duda, estoy tratando de guardar los valores que obtengo del conversor ad en una memoria eeprom externa, pero no se si voy por buen camino, estoy usando ua memoria 24lc256:

#include <16F877A.h>                ///   libreria para el manejo del pic16f877a
#device ADC=10
#include <stdlib.h>
#include "24256.c"
#priority rda,ad,timer1,timer0
#use delay(clock=20000000)          ///   declara  la frecuencia del cristal 20mhz
#use RS232(BAUD=9600,BITS=8,PARITY=N,XMIT=PIN_C6,RCV=PIN_C7)

#use fast_io(A)
#use fast_io(B)
#use fast_io(C)                     ///   con esta instruccion evitamos que
#use fast_io(D)                     ///   se este configurando cada vez que usamos
#use fast_io(E)                     ///   alguna instruccion de entrada o salida

#byte porta = 5
#byte portb = 6
#byte portc = 7                     /// se definen direcciones de memoria
#byte portd = 8
#byte porte = 9

#define EEPROM_SDA PIN_c4
#define EEPROM_SCL PIN_c3

   int nums[7];
   int temporal;
   int cont_letras;                    //variable para contar los 8 numeros que se puede entrar por Tx serie
   int16 time;                           //hasta 300 segundos entre recuperaciones de muestras
   int16 cant_var;                       //hasta 2000 muestras que es necesario recojer
   int cont_seg;
   int16 cont_time;
   int16 cont_var;
   int estado_leds;
   int var_in_rand;
   int16 lectura_ad;
   int canal_ad;

int Tabla(int a)        //tabla para visualizar numeros por el 7segmentos
{
  switch(a)
  {
      CASE 0:RETURN 0b00111111;
      CASE 1:RETURN 0B00000110;
      CASE 2:RETURN 0B01011011;
      CASE 3:RETURN 0B01001111;
      CASE 4:RETURN 0B01100110;
      CASE 5:RETURN 0B01101101;
      CASE 6:RETURN 0B01111101;
      CASE 7:RETURN 0B00000111;
      CASE 8:RETURN 0B01111111;
      CASE 9:RETURN 0B01100111;
  }
}

int Is_num(int a)
{
   if(a>=48 && a<=57)
    return 0;                          //si es 0 es un numero sino es otro
   return 1;
}

void actualiza_led(int i)
{
   switch(i)
   {
   case 0: portb= 0B11111110;         //PC
           portd= 0B01110011;
           delay_ms(50);
           portb= 0B11111101;
           portd= 0B00111001;
           break;
   case 1: portb= 0B11111110;         //Ad
           portd= 0B01110111;
           delay_ms(50);
           portb= 0B11111101;
           portd= 0B01011110;
           break;
   case 2: portb= 0B11111110;         //Sd
           portd= 0B01101101;
           delay_ms(50);
           portb= 0B11111101;
           portd= 0B01011110;
           break;
   }
}


#use delay(clock=20000000)

void LeerAD(int canal)
{
   lectura_ad = 0;
   setup_port_a( ALL_ANALOG );
   setup_adc( ADC_CLOCK_INTERNAL );
   set_adc_channel(canal);
   lectura_ad = read_adc();
   delay_ms(20);
   setup_adc (adc_off);

}



#int_TIMER0                         //directiva para it del timer0
void TIMER0_isr()
{
    actualiza_led(estado_leds);
    set_timer0(81);
}

#int_TIMER1                         //directiva para it del timer0
void TIMER1_isr()
{
   if(cont_seg > 9)
   {
      cont_seg = 0;
      if(cont_time < time)
         cont_time++;
      else
      {
         cont_time = 0;
         canal_ad = 0;
         while (canal_ad>8)
         {
         LeerAD(canal_ad);
         write_ext_eeprom(_mul(cont_var,2),lectura_ad);
         canal_ad++;
         }
      }
   }
   cont_seg++;
   set_timer1(3063);
}

#int_rda
void rda_isr()
{
   if(cont_letras < 7)
   {
      temporal = getc();
      if(Is_num(temporal)==0)
      {
         temporal =temporal-48;
         nums[cont_letras] = temporal;
         printf ("%d",nums[cont_letras]);
         cont_letras++;
      }
      else
      {
         cont_letras = 0;
         printf ("Error");
      }
   }
}


void configurar(void)                  //configuraciones
{
   enable_interrupts(INT_TIMER0);         //habilitar el timer0
   enable_interrupts(INT_TIMER1);         //habilitar el timer1
   enable_interrupts(INT_RDA);            //habilitar para comunicación serie
   enable_interrupts(GLOBAL);             //habilitar el bit de it global

   set_tris_d(0x00);
   set_tris_b(0x00);
}


void main()
{
   cont_seg = 0;
   estado_leds = 0;
   cont_letras = 0;
   var_in_rand = 0;
   cont_time = 0;
   canal_ad = 0;
   configurar();
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
   set_timer0(81);
   while(var_in_rand == 0)
   {
      while(cont_letras < 7){}
      cant_var = _mul(nums[0],1000) + _mul(nums[1],100) + _mul(nums[2],10) + nums[3];
      time = _mul(nums[4],100) + _mul(nums[5],10) + nums[6];
      var_in_rand = 1;
      if(time>300 || time<1)
      {
         printf (" Tiempo fuera de rango. ");
         cont_letras = 0;
         var_in_rand = 0;
      }
     else
      if(cant_var>2000)
      {
         printf (" Cantidad de muestras fuera de rango. ");
         cont_letras = 0;
         var_in_rand = 0;
      }
   }
   clear_interrupt(int_rda);
   estado_leds = 1;
   init_ext_eeprom();
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
   set_timer1(3063);
   while(1){}


}

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Duda sobre conversor ad del pic 16f877a
« Respuesta #3 en: 27 de Abril de 2011, 12:58:45 »
Puedes usar la libreria external_eeprom.c y las funciones write_int16_ext_eeprom y read_int16_ext_eeprom


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado yeestrada

  • PIC10
  • *
  • Mensajes: 15
Re: Duda sobre conversor ad del pic 16f877a
« Respuesta #4 en: 28 de Abril de 2011, 00:05:05 »
Puedes usar la libreria external_eeprom.c y las funciones write_int16_ext_eeprom y read_int16_ext_eeprom


Saludos!

bueno, ya lo estoy utilizando y no me lee ni me escribe en la eeprom, no se si el problema sea en el diseño del hardware, aqui esta la imagen de mi diseño y mi programa nuevamente, por favor diganme que estoy haciendo mal

diseño:
http://www.filefactory.com/file/cbf3d60/n/disenno.jpg

programa:


#include <16F877A.h>                ///   libreria para el manejo del pic16f877a
#device ADC=10
#include <stdlib.h>
#include "24256.c"
#include "external_eeprom.c"
#priority rda,ad,timer1,timer0
#use delay(clock=20000000)          ///   declara  la frecuencia del cristal 20mhz
#use RS232(BAUD=9600,BITS=8,PARITY=N,XMIT=PIN_C6,RCV=PIN_C7)

#use fast_io(A)
#use fast_io(B)
#use fast_io(C)                     ///   con esta instruccion evitamos que
#use fast_io(D)                     ///   se este configurando cada vez que usamos
#use fast_io(E)                     ///   alguna instruccion de entrada o salida

#byte porta = 5
#byte portb = 6
#byte portc = 7                     /// se definen direcciones de memoria
#byte portd = 8
#byte porte = 9

#define EEPROM_SDA PIN_c4
#define EEPROM_SCL PIN_c3

   int nums[7];
   int temporal;
   int cont_letras;                    //variable para contar los 8 numeros que se puede entrar por Tx serie
   int16 time;                           //hasta 300 segundos entre recuperaciones de muestras
   int16 cant_var;                       //hasta 2000 muestras que es necesario recojer
   int cont_seg;
   int16 cont_time;
   int16 cont_var;
   int estado_leds;
   int var_in_rand;
   int16 lectura_ad;
   int canal_ad;

int Tabla(int a)        //tabla para visualizar numeros por el 7segmentos
{
  switch(a)
  {
      CASE 0:RETURN 0b00111111;
      CASE 1:RETURN 0B00000110;
      CASE 2:RETURN 0B01011011;
      CASE 3:RETURN 0B01001111;
      CASE 4:RETURN 0B01100110;
      CASE 5:RETURN 0B01101101;
      CASE 6:RETURN 0B01111101;
      CASE 7:RETURN 0B00000111;
      CASE 8:RETURN 0B01111111;
      CASE 9:RETURN 0B01100111;
  }
}

int Is_num(int a)
{
   if(a>=48 && a<=57)
    return 0;                          //si es 0 es un numero sino es otro
   return 1;
}

void actualiza_led(int i)
{
   switch(i)
   {
   case 0: portb= 0B11111110;         //PC
           portd= 0B01110011;
           delay_ms(50);
           portb= 0B11111101;
           portd= 0B00111001;
           break;
   case 1: portb= 0B11111110;         //Ad
           portd= 0B01110111;
           delay_ms(50);
           portb= 0B11111101;
           portd= 0B01011110;
           break;
   case 2: portb= 0B11111110;         //Sd
           portd= 0B01101101;
           delay_ms(50);
           portb= 0B11111101;
           portd= 0B01011110;
           break;
   }
}

void write_int16_eeprom(int16 direccion, int16 dato)
{
   int dato_0,dato_1;

   dato_0 = make8(dato,0);   //MSB
   dato_1 = make8(dato,1);
   
   write_ext_eeprom(direccion,dato_0);
   direccion++;
   write_ext_eeprom(direccion,dato_1);
   
   printf("ya");
   return;
}

int16 read_int16_eeprom(int16 direccion)
{
   int16 dato;
   int dato_0,dato_1;
   

   dato_0=read_ext_eeprom(direccion);
   direccion++;
   dato_1=read_ext_eeprom(direccion);

   dato=make16(dato_0,dato_1);
   return(dato);
}

#use delay(clock=20000000)

void LeerAD(int canal)
{
   lectura_ad = 0;
   setup_port_a( ALL_ANALOG );
   setup_adc( ADC_CLOCK_INTERNAL );
   set_adc_channel(canal);
   lectura_ad = read_adc();
   delay_ms(20);
   setup_adc (adc_off);

}



#int_TIMER0                         //directiva para it del timer0
void TIMER0_isr()
{
    actualiza_led(estado_leds);
    set_timer0(81);
}

#int_TIMER1                         //directiva para it del timer0
void TIMER1_isr()
{
   if(cont_seg > 9)
   {
      cont_seg = 0;
      if(cont_time < time)
         cont_time++;
      else
      {
         cont_time = 0;
         canal_ad = 0;
         while (canal_ad>8)
         {
         LeerAD(canal_ad);
         write_ext_eeprom(_mul(cont_var,2),lectura_ad);
         canal_ad++;
         }
      }
   }
   cont_seg++;
   set_timer1(3063);
}

#int_rda
void rda_isr()
{
   if(cont_letras < 7)
   {
      temporal = getc();
      if(Is_num(temporal)==0)
      {
         temporal =temporal-48;
         nums[cont_letras] = temporal;
         printf ("%d",nums[cont_letras]);
         cont_letras++;
      }
      else
      {
         cont_letras = 0;
         printf ("Error");
      }
   }
}


void configurar(void)                  //configuraciones
{
   enable_interrupts(INT_TIMER0);         //habilitar el timer0
   enable_interrupts(INT_TIMER1);         //habilitar el timer1
   enable_interrupts(INT_RDA);            //habilitar para comunicación serie
   enable_interrupts(GLOBAL);             //habilitar el bit de it global

   set_tris_d(0x00);
   set_tris_b(0x00);
}
#use delay(clock=20000000)

void main()
{
   cont_seg = 0;
   estado_leds = 0;
   cont_letras = 0;
   var_in_rand = 0;
   cont_time = 0;
   canal_ad = 0;
   configurar();
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
   set_timer0(81);
   while(var_in_rand == 0)
   {
      while(cont_letras < 7){}
      cant_var = _mul(nums[0],1000) + _mul(nums[1],100) + _mul(nums[2],10) + nums[3];
      time = _mul(nums[4],100) + _mul(nums[5],10) + nums[6];
      var_in_rand = 1;
      if(time>300 || time<1)
      {
         printf (" Tiempo fuera de rango. ");
         cont_letras = 0;
         var_in_rand = 0;
      }
     else
      if(cant_var>2000)
      {
         printf (" Cantidad de muestras fuera de rango. ");
         cont_letras = 0;
         var_in_rand = 0;
      }
   }
   clear_interrupt(int_rda);
   estado_leds = 1;
   LeerAD(0);
   //read_ext_eeprom(dir)
   //write_ext_eeprom(0,(read_ext_eeprom(0))+1);
   //printf(" %2x",lectura_ad);
   
   /*write_ext_eeprom(0,lectura_ad);
   printf(" %d",read_ext_eeprom(0));
   delay_ms(20);
   printf("%d",read_ext_eeprom(1));*/
   init_ext_eeprom();
   write_int16_ext_eeprom(0, lectura_ad);
   
   
   delay_ms(100);
   lectura_ad = read_int16_ext_eeprom(50);
   delay_ms(100);
   
   printf("%2x",lectura_ad);
   /*setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
   set_timer1(3063);*/
   while(1){}


}

Desconectado bmb

  • PIC18
  • ****
  • Mensajes: 423
Re: Duda sobre conversor ad del pic 16f877a
« Respuesta #5 en: 28 de Abril de 2011, 00:43:32 »
Hola yeestrada, estos defines:
Código: C
  1. #define EEPROM_SDA PIN_c4
  2. #define EEPROM_SCL PIN_c3
deben ir antes de:
Código: C
  1. #include "24256.c"
Estas líneas:
Código: C
  1. setup_port_a( ALL_ANALOG );
  2.    setup_adc( ADC_CLOCK_INTERNAL );
No deben ir en la función en donde están ahora, sino en la función void configurar(void).  Es lo que veo por el momento.

Saludos!

Desconectado yeestrada

  • PIC10
  • *
  • Mensajes: 15
Re: Duda sobre conversor ad del pic 16f877a
« Respuesta #6 en: 28 de Abril de 2011, 09:30:32 »
hola bmb, ya modifique lo que me sugeriste, y finalmente logro que escriba y lea de la eeprom sin que el programa se pierda como hacia antes, sin embargo parece que no guarda o lee bien, pq guarde el valor de lectura_ad (lectura del conversor ad) donde lo guarde ya sea en la pos 50 o 0 siempre me devuelve 00,
asi queda despues que pruebo lo que me dijiste:


#include <16F877A.h>                ///   libreria para el manejo del pic16f877a
#device ADC=10
#include <stdlib.h>

#define EEPROM_SDA PIN_c4
#define EEPROM_SCL PIN_c3

#include "24256.c"
#include "external_eeprom.c"
#priority rda,ad,timer1,timer0
#use delay(clock=20000000)          ///   declara  la frecuencia del cristal 20mhz
#use RS232(BAUD=9600,BITS=8,PARITY=N,XMIT=PIN_C6,RCV=PIN_C7)

#use fast_io(A)
#use fast_io(B)
#use fast_io(C)                     ///   con esta instruccion evitamos que
#use fast_io(D)                     ///   se este configurando cada vez que usamos
#use fast_io(E)                     ///   alguna instruccion de entrada o salida

#byte porta = 5
#byte portb = 6
#byte portc = 7                     /// se definen direcciones de memoria
#byte portd = 8
#byte porte = 9

   int nums[7];
   int temporal;
   int cont_letras;                    //variable para contar los 8 numeros que se puede entrar por Tx serie
   int16 time;                           //hasta 300 segundos entre recuperaciones de muestras
   int16 cant_var;                       //hasta 2000 muestras que es necesario recojer
   int cont_seg;
   int16 cont_time;
   int16 cont_var;
   int estado_leds;
   int var_in_rand;
   int16 lectura_ad;
   int canal_ad;

int Tabla(int a)        //tabla para visualizar numeros por el 7segmentos
{
  switch(a)
  {
      CASE 0:RETURN 0b00111111;
      CASE 1:RETURN 0B00000110;
      CASE 2:RETURN 0B01011011;
      CASE 3:RETURN 0B01001111;
      CASE 4:RETURN 0B01100110;
      CASE 5:RETURN 0B01101101;
      CASE 6:RETURN 0B01111101;
      CASE 7:RETURN 0B00000111;
      CASE 8:RETURN 0B01111111;
      CASE 9:RETURN 0B01100111;
  }
}

int Is_num(int a)
{
   if(a>=48 && a<=57)
    return 0;                          //si es 0 es un numero sino es otro
   return 1;
}

void actualiza_led(int i)
{
   switch(i)
   {
   case 0: portb= 0B11111110;         //PC
           portd= 0B01110011;
           delay_ms(50);
           portb= 0B11111101;
           portd= 0B00111001;
           break;
   case 1: portb= 0B11111110;         //Ad
           portd= 0B01110111;
           delay_ms(50);
           portb= 0B11111101;
           portd= 0B01011110;
           break;
   case 2: portb= 0B11111110;         //Sd
           portd= 0B01101101;
           delay_ms(50);
           portb= 0B11111101;
           portd= 0B01011110;
           break;
   }
}

void write_int16_eeprom(int16 direccion, int16 dato)
{
   int dato_0,dato_1;

   dato_0 = make8(dato,0);   //MSB
   dato_1 = make8(dato,1);

   write_ext_eeprom(direccion,dato_0);
   direccion++;
   write_ext_eeprom(direccion,dato_1);

   printf("ya");
   return;
}

int16 read_int16_eeprom(int16 direccion)
{
   int16 dato;
   int dato_0,dato_1;


   dato_0=read_ext_eeprom(direccion);
   direccion++;
   dato_1=read_ext_eeprom(direccion);

   dato=make16(dato_0,dato_1);
   return(dato);
}

#use delay(clock=20000000)

void LeerAD(int canal)
{
   lectura_ad = 0;
   set_adc_channel(canal);
   lectura_ad = read_adc();
   delay_ms(20);
   setup_adc (adc_off);
}



#int_TIMER0                         //directiva para it del timer0
void TIMER0_isr()
{
    actualiza_led(estado_leds);
    set_timer0(81);
}

#int_TIMER1                         //directiva para it del timer0
void TIMER1_isr()
{
   if(cont_seg > 9)
   {
      cont_seg = 0;
      if(cont_time < time)
         cont_time++;
      else
      {
         cont_time = 0;
         canal_ad = 0;
         while (canal_ad>8)
         {
         LeerAD(canal_ad);
         write_ext_eeprom(_mul(cont_var,2),lectura_ad);
         canal_ad++;
         }
      }
   }
   cont_seg++;
   set_timer1(3063);
}

#int_rda
void rda_isr()
{
   if(cont_letras < 7)
   {
      temporal = getc();
      if(Is_num(temporal)==0)
      {
         temporal =temporal-48;
         nums[cont_letras] = temporal;
         printf ("%d",nums[cont_letras]);
         cont_letras++;
      }
      else
      {
         cont_letras = 0;
         printf ("Error");
      }
   }
}


void configurar(void)                  //configuraciones
{
   enable_interrupts(INT_TIMER0);         //habilitar el timer0
   enable_interrupts(INT_TIMER1);         //habilitar el timer1
   enable_interrupts(INT_RDA);            //habilitar para comunicación serie
   enable_interrupts(GLOBAL);             //habilitar el bit de it global
   setup_port_a( ALL_ANALOG );
   setup_adc( ADC_CLOCK_INTERNAL );

   set_tris_d(0x00);
   set_tris_b(0x00);
}
#use delay(clock=20000000)

void main()
{
   cont_seg = 0;
   estado_leds = 0;
   cont_letras = 0;
   var_in_rand = 0;
   cont_time = 0;
   canal_ad = 0;
   configurar();
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
   set_timer0(81);
   while(var_in_rand == 0)
   {
      while(cont_letras < 7){}
      cant_var = _mul(nums[0],1000) + _mul(nums[1],100) + _mul(nums[2],10) + nums[3];
      time = _mul(nums[4],100) + _mul(nums[5],10) + nums[6];
      var_in_rand = 1;
      if(time>300 || time<1)
      {
         printf (" Tiempo fuera de rango. ");
         cont_letras = 0;
         var_in_rand = 0;
      }
     else
      if(cant_var>2000)
      {
         printf (" Cantidad de muestras fuera de rango. ");
         cont_letras = 0;
         var_in_rand = 0;
      }
   }
   clear_interrupt(int_rda);
   estado_leds = 1;
   LeerAD(0);
   //read_ext_eeprom(dir)
   //write_ext_eeprom(0,(read_ext_eeprom(0))+1);
   //printf(" %2x",lectura_ad);

   /*write_ext_eeprom(0,lectura_ad);
   printf(" %d",read_ext_eeprom(0));
   delay_ms(20);*/
   printf(" %2x ",lectura_ad);
   lectura_ad=0;
   init_ext_eeprom();
   write_int16_ext_eeprom(0, lectura_ad);


   delay_ms(100);
   lectura_ad = read_int16_ext_eeprom(0);
   delay_ms(100);

   printf("%2x",lectura_ad);
   /*setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
   set_timer1(3063);*/
   while(1){}


}

Desconectado bmb

  • PIC18
  • ****
  • Mensajes: 423
Re: Duda sobre conversor ad del pic 16f877a
« Respuesta #7 en: 28 de Abril de 2011, 12:36:14 »
Hola yeestrada, la verdad es que me queda un poco difícil decirte el por que no está escibiendo bien el dato en la eeprom.  Solo te puedo hacer algunas sugerencias más a ver si te vas acercando a la solución.

Primero te recomiendo utilizar un encabezado como el que te muestro (no veo los fuses en tu código):

Creo que en la función int Is_num(int a) te está faltando una sentencia else en donde te muestro comentado.

La función void configurar(void) puede quedar como te muestro y allí, como verás la inicialización de Timer1 sigue comentada como la tenías (en otro lado), lo que no es normal.

Código: C
  1. #include <16F877A.h>
  2. #device adc=10
  3.  
  4. #FUSES NOWDT                    //No Watch Dog Timer
  5. #FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
  6. #FUSES NOBROWNOUT               //No brownout reset
  7. #FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
  8.  
  9. #use delay(clock=20000000)
  10. #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
  11.  
  12. #define EEPROM_SDA PIN_c4
  13. #define EEPROM_SCL PIN_c3
  14. #include "24256.c"
  15. #include "external_eeprom.c"
  16. #include <stdlib.h>
  17.  
  18. // #priority rda,ad,timer1,timer0
  19.  
  20. // #use fast_io(A)
  21. #use fast_io(B)
  22. // #use fast_io(C)                     ///   con esta instruccion evitamos que
  23. #use fast_io(D)                     ///   se este configurando cada vez que usamos
  24. // #use fast_io(E)                     ///   alguna instruccion de entrada o salida
  25.  
  26. // #byte porta = 5
  27. #byte portb = 6
  28. // #byte portc = 7                     /// se definen direcciones de memoria
  29. #byte portd = 8
  30. // #byte porte = 9
  31.  
  32. int nums[7];
  33. int temporal;
  34. int cont_letras;                    //variable para contar los 8 numeros que se puede entrar por Tx serie
  35. int16 time;                         //hasta 300 segundos entre recuperaciones de muestras
  36. int16 cant_var;                     //hasta 2000 muestras que es necesario recojer
  37. int cont_seg;
  38. int16 cont_time;
  39. int16 cont_var;
  40. int estado_leds;
  41. int var_in_rand;
  42. int16 lectura_ad;
  43. int canal_ad;
  44.  
  45. int Tabla(int a)        //tabla para visualizar numeros por el 7segmentos
  46. {
  47.   switch(a)
  48.   {
  49.       CASE 0:RETURN 0b00111111;
  50.       CASE 1:RETURN 0B00000110;
  51.       CASE 2:RETURN 0B01011011;
  52.       CASE 3:RETURN 0B01001111;
  53.       CASE 4:RETURN 0B01100110;
  54.       CASE 5:RETURN 0B01101101;
  55.       CASE 6:RETURN 0B01111101;
  56.       CASE 7:RETURN 0B00000111;
  57.       CASE 8:RETURN 0B01111111;
  58.       CASE 9:RETURN 0B01100111;
  59.   }
  60. }
  61.  
  62. int Is_num(int a)
  63. {
  64.    if(a>=48 && a<=57)
  65.       return 0;                          //si es 0 es un numero sino es otro
  66. // else                                  // Falta este else?
  67.       return 1;
  68. }
  69.  
  70. void actualiza_led(int i)
  71. {
  72.    switch(i)
  73.    {
  74.    case 0: portb= 0B11111110;         //PC
  75.            portd= 0B01110011;
  76.            delay_ms(50);
  77.            portb= 0B11111101;
  78.            portd= 0B00111001;
  79.            break;
  80.    case 1: portb= 0B11111110;         //Ad
  81.            portd= 0B01110111;
  82.            delay_ms(50);
  83.            portb= 0B11111101;
  84.            portd= 0B01011110;
  85.            break;
  86.    case 2: portb= 0B11111110;         //Sd
  87.            portd= 0B01101101;
  88.            delay_ms(50);
  89.            portb= 0B11111101;
  90.            portd= 0B01011110;
  91.            break;
  92.    }
  93. }
  94.  
  95. void write_int16_eeprom(int16 direccion, int16 dato)
  96. {
  97.    int dato_0,dato_1;
  98.  
  99.    dato_0 = make8(dato,0);   //MSB
  100.    dato_1 = make8(dato,1);
  101.  
  102.    write_ext_eeprom(direccion,dato_0);
  103.    direccion++;
  104.    write_ext_eeprom(direccion,dato_1);
  105.  
  106.    printf("ya");
  107.    return;
  108. }
  109.  
  110. int16 read_int16_eeprom(int16 direccion)
  111. {
  112.    int16 dato;
  113.    int dato_0,dato_1;
  114.  
  115.  
  116.    dato_0=read_ext_eeprom(direccion);
  117.    direccion++;
  118.    dato_1=read_ext_eeprom(direccion);
  119.  
  120.    dato=make16(dato_0,dato_1);
  121.    return(dato);
  122. }
  123.  
  124. void LeerAD(int canal)
  125. {
  126.    lectura_ad = 0;
  127.    set_adc_channel(canal);
  128.    lectura_ad = read_adc();
  129.    delay_ms(20);
  130.    setup_adc (adc_off);
  131. }
  132.  
  133. void configurar(void)                  //configuraciones
  134. {
  135.    setup_adc_ports(ALL_ANALOG);
  136.    setup_adc( ADC_CLOCK_INTERNAL );
  137.    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
  138. //   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
  139.    enable_interrupts(INT_RDA);
  140.    enable_interrupts(INT_TIMER1);
  141.    enable_interrupts(INT_TIMER0);
  142.    enable_interrupts(GLOBAL);
  143.  
  144.    set_timer0(81);  
  145. //   set_timer1(3063);
  146.  
  147.    set_tris_d(0x00);
  148.    set_tris_b(0x00);
  149.    init_ext_eeprom();
  150. }
  151.  
  152. #int_RDA
  153. void  RDA_isr(void)
  154. {
  155.    if(cont_letras < 7)
  156.    {
  157.       temporal = getc();
  158.       if(Is_num(temporal)==0)
  159.       {
  160.          temporal =temporal-48;
  161.          nums[cont_letras] = temporal;
  162.          printf ("%d",nums[cont_letras]);
  163.          cont_letras++;
  164.       }
  165.       else
  166.       {
  167.          cont_letras = 0;
  168.          printf ("Error");
  169.       }
  170.    }
  171. }
  172.  
  173. #int_TIMER1
  174. void  TIMER1_isr(void)
  175. {
  176.    if(cont_seg > 9)
  177.    {
  178.       cont_seg = 0;
  179.       if(cont_time < time)
  180.          cont_time++;
  181.       else
  182.       {
  183.          cont_time = 0;
  184.          canal_ad = 0;
  185.          while (canal_ad>0);
  186.          {
  187.          LeerAD(canal_ad);
  188.          write_ext_eeprom(_mul(cont_var,2),lectura_ad);
  189.          canal_ad++;
  190.          }
  191.       }
  192.    }
  193.    cont_seg++;
  194.    set_timer1(3063);
  195. }
  196.  
  197. #int_TIMER0
  198. void  TIMER0_isr(void)
  199. {
  200.     actualiza_led(estado_leds);
  201.     set_timer0(81);
  202. }
  203.  
  204. void main()
  205. {
  206.    cont_seg = 0;
  207.    estado_leds = 0;
  208.    cont_letras = 0;
  209.    var_in_rand = 0;
  210.    cont_time = 0;
  211.    canal_ad = 0;
  212.  
  213.    configurar();
  214.  
  215.    while(var_in_rand == 0)
  216.    {
  217.       while(cont_letras < 7){}
  218.       cant_var = _mul(nums[0],1000) + _mul(nums[1],100) + _mul(nums[2],10) + nums[3];
  219.       time = _mul(nums[4],100) + _mul(nums[5],10) + nums[6];
  220.       var_in_rand = 1;
  221.       if(time>300 || time<1)
  222.       {
  223.          printf (" Tiempo fuera de rango. ");
  224.          cont_letras = 0;
  225.          var_in_rand = 0;
  226.       }
  227.      else
  228.       if(cant_var>2000)
  229.       {
  230.          printf (" Cantidad de muestras fuera de rango. ");
  231.          cont_letras = 0;
  232.          var_in_rand = 0;
  233.       }
  234.    }
  235.    clear_interrupt(int_rda);
  236.  
  237.    estado_leds = 1;
  238.    LeerAD(0);
  239.    //read_ext_eeprom(dir)
  240.    //write_ext_eeprom(0,(read_ext_eeprom(0))+1);
  241.    //printf(" %2x",lectura_ad);
  242.  
  243.    /*write_ext_eeprom(0,lectura_ad);
  244.    printf(" %d",read_ext_eeprom(0));
  245.    delay_ms(20);*/
  246.    printf(" %2x ",lectura_ad);
  247.    lectura_ad=0;
  248.    write_int16_ext_eeprom(0, lectura_ad);
  249.  
  250.  
  251.    delay_ms(100);
  252.    lectura_ad = read_int16_ext_eeprom(0);
  253.    delay_ms(100);
  254.  
  255.    printf("%2x",lectura_ad);
  256.  
  257.    while(1){}
  258.  
  259. }

No se si estás teniendo en cuenta que después de que salga del bucle while(var_in_rand == 0) el programa ejecutará las instrucciones siguientes y al encontrarse al final con el bucle while(1){} solo seguirá ejecutando lo que encuentre en los códigos de interrupción cuando llegue a ellos.

De todos modos, al compilar el código me salen muchas advertencias de deshabilitación de las interrupciones por muchas causas.  Creo que deberías reconsiderar tu programación tratando de utilizar más banderas y validarlas en el código principal.

Saludos!

Desconectado yeestrada

  • PIC10
  • *
  • Mensajes: 15
Re: Duda sobre conversor ad del pic 16f877a
« Respuesta #8 en: 28 de Abril de 2011, 12:58:19 »
bueno, los fuses es cierto que no he puesto ninguno, pues no se trabajar con ellos, lo del else es a proposito, pues si no entra en el if automaticamente retorna lo otro, y si dentro del if retorna, pues automaticamente sale del metodo.Lo de las prioridades que comentariaste, no se relmente si deberia comentariarlo, pues necesito establecer prioridades para las interrupciones. Por otro lado en esa version ya encontre el problema y logre leer y escribir en la eeprom, el problema real lo tengo ahora, que ncesito realizar lecturas cada cierto tiempo del conversor ad y guardar la lectura en la eeprom. Inicialmente puse el codigo este dentro de la it del timer1, pero para evitar sobrecargar el timer lo saque por si era ese el problema, y sigue sin trabajar, realmente no se que pasa, que delay hay que darle para qu guarde en la eeprom?


saludos yordan

#include <16F877A.h>                ///   libreria para el manejo del pic16f877a
#device ADC=10
#include <stdlib.h>

#define EEPROM_SDA PIN_c4
#define EEPROM_SCL PIN_c3

#include "24256.c"
#include "external_eeprom.c"
#priority rda,ad,timer1,timer0
#use delay(clock=20000000)          ///   declara  la frecuencia del cristal 20mhz
#use RS232(BAUD=9600,BITS=8,PARITY=N,XMIT=PIN_C6,RCV=PIN_C7)

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O

#use fast_io(A)
#use fast_io(B)
#use fast_io(C)                     ///   con esta instruccion evitamos que
#use fast_io(D)                     ///   se este configurando cada vez que usamos
#use fast_io(E)                     ///   alguna instruccion de entrada o salida

#byte porta = 5
#byte portb = 6
#byte portc = 7                     /// se definen direcciones de memoria
#byte portd = 8
#byte porte = 9

   int nums[7];
   int temporal;
   int cont_letras;                    //variable para contar los 8 numeros que se puede entrar por Tx serie
   int16 time;                           //hasta 300 segundos entre recuperaciones de muestras
   int16 cant_var;                       //hasta 2000 muestras que es necesario recojer
   int cont_seg;
   int16 cont_time;
   int16 cont_var;
   int estado_leds;
   int var_in_rand;
   int16 lectura_ad;
   int canal_ad;

int Tabla(int a)        //tabla para visualizar numeros por el 7segmentos
{
  switch(a)
  {
      CASE 0:RETURN 0b00111111;
      CASE 1:RETURN 0B00000110;
      CASE 2:RETURN 0B01011011;
      CASE 3:RETURN 0B01001111;
      CASE 4:RETURN 0B01100110;
      CASE 5:RETURN 0B01101101;
      CASE 6:RETURN 0B01111101;
      CASE 7:RETURN 0B00000111;
      CASE 8:RETURN 0B01111111;
      CASE 9:RETURN 0B01100111;
  }
}

int Is_num(int a)
{
   if(a>=48 && a<=57)
    return 0;                          //si es 0 es un numero sino es otro
   return 1;
}

void actualiza_led(int i)
{
   switch(i)
   {
   case 0: portb= 0B11111110;         //PC
           portd= 0B01110011;
           delay_ms(50);
           portb= 0B11111101;
           portd= 0B00111001;
           break;
   case 1: portb= 0B11111110;         //Ad
           portd= 0B01110111;
           delay_ms(50);
           portb= 0B11111101;
           portd= 0B01011110;
           break;
   case 2: portb= 0B11111110;         //Sd
           portd= 0B01101101;
           delay_ms(50);
           portb= 0B11111101;
           portd= 0B01011110;
           break;
   }
}


#use delay(clock=20000000)

void LeerAD(int canal)
{
   lectura_ad = 0;
   set_adc_channel(canal);
   lectura_ad = read_adc();
   delay_ms(20);
   setup_adc (adc_off);
}



#int_TIMER0                         //directiva para it del timer0
void TIMER0_isr()
{
    actualiza_led(estado_leds);
    set_timer0(81);
}
#use delay(clock=20000000)

#int_TIMER1                         //directiva para it del timer0
void TIMER1_isr()
{

      if(cont_seg > 9)
      {
         cont_seg = 0;
         printf("s ");
         if(cont_time < time)
            cont_time++;     
         else
         {
            temporal =1;   
           
           // printf("var");
         }
      }
   //}
  // else
    //clear_interrupt(int_TIMER1);
   
   cont_seg++;
   set_timer1(3063);
   
}

#int_rda
void rda_isr()
{
   if(cont_letras < 7)
   {
      temporal = getc();
      if(Is_num(temporal)==0)
      {
         temporal =temporal-48;
         nums[cont_letras] = temporal;
         printf ("%d",nums[cont_letras]);
         cont_letras++;
      }
      else
      {
         cont_letras = 0;
         printf ("Error");
      }
   }
}


void configurar(void)                  //configuraciones
{
   enable_interrupts(INT_TIMER0);         //habilitar el timer0
   enable_interrupts(INT_TIMER1);         //habilitar el timer1
   enable_interrupts(INT_RDA);            //habilitar para comunicación serie
   enable_interrupts(GLOBAL);             //habilitar el bit de it global
   setup_port_a( ALL_ANALOG );
   setup_adc( ADC_CLOCK_INTERNAL );

   set_tris_d(0x00);
   set_tris_b(0x00);
}

#use delay(clock=20000000)

void main()
{
   cont_seg = 0;
   estado_leds = 0;
   cont_letras = 0;
   var_in_rand = 0;
   cont_time = 1;
   canal_ad = 0;
   cont_var = 0;
   configurar();
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
   set_timer0(81);
   while(var_in_rand == 0)
   {
      while(cont_letras < 7){}
      cant_var = _mul(nums[0],1000) + _mul(nums[1],100) + _mul(nums[2],10) + nums[3];
      time = _mul(nums[4],100) + _mul(nums[5],10) + nums[6];
      var_in_rand = 1;
      if(time>300 || time<1)
      {
         printf (" Tiempo fuera de rango. ");
         cont_letras = 0;
         var_in_rand = 0;
      }
     else
      if(cant_var>2000)
      {
         printf (" Cantidad de muestras fuera de rango. ");
         cont_letras = 0;
         var_in_rand = 0;
      }
   }
   //clear_interrupt(int_rda);
   estado_leds = 1;
   //LeerAD(0);
   //read_ext_eeprom(dir)
   //write_ext_eeprom(0,(read_ext_eeprom(0))+1);
   //printf(" %2x",lectura_ad);

   /*write_ext_eeprom(0,lectura_ad);
   printf(" %d",read_ext_eeprom(0));
   delay_ms(20);
   
   
   printf(" %2x ",lectura_ad);
   
   
   write_int16_ext_eeprom(0, lectura_ad);


   lectura_ad=0;

   delay_ms(100);
   
   delay_ms(100);*/

   init_ext_eeprom();
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
   set_timer1(3063);
   while(cont_var<cant_var)
   {
      if(temporal ==1)
      {
       clear_interrupt(int_timer1);
         cont_time = 1;
         canal_ad = 0;
         while (canal_ad<8)
         {
           printf("L");
           LeerAD(canal_ad);
           write_int16_ext_eeprom(cont_var, lectura_ad);
           //delay_ms(20);
           canal_ad++;           
               
               /*delay_ms(20);
               canal_ad++;*/
          }
           cont_var++;
           printf("var");
           temporal =0;
           enable_interrupts(INT_TIMER1);

      }
   }
   printf("ya");

}
 

Desconectado bmb

  • PIC18
  • ****
  • Mensajes: 423
Re: Duda sobre conversor ad del pic 16f877a
« Respuesta #9 en: 28 de Abril de 2011, 13:19:16 »
Alguna vez he usado la librería para eeprom externa y no es necesario adicionar un delay.  De todos modos, te recomiendo leer más detenidamente el código que te pasé; por ejemplo esto: setup_port_a( ALL_ANALOG ); sigue mal escrito.

Saludos!

Edito: Respecto a lo de las prioridades, si dos interrupciones ocurren a la vez, la primera en la lista es la que atiende primero.  Cuando una interrupción ya está activa, no es interrumpida por ninguna otra acción.  Como en tu caso tienes tantas demoras en todas las interrupciones (cosa que puedes corregir), creo que las prioridades por el momento no te van a servir de mucho, pero en realidad no hay ningún problema si las dejas.
« Última modificación: 28 de Abril de 2011, 13:43:14 por bmb »


 

anything