Autor Tema: Imprecision en cuenta atras en tiempo real  (Leído 1833 veces)

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

Desconectado ituarte

  • PIC12
  • **
  • Mensajes: 69
Imprecision en cuenta atras en tiempo real
« en: 12 de Agosto de 2013, 07:58:00 »
Buenas,

Estoy haciendo una cuenta atras de los segundos que tiene un dia (86400), y para ello utilizo un PIC16F84A conectado a 5 displays de 7 segmentos. Para calcular un segundo exacto utilizo la interrupcion interna por desbordamiento del PIC, pero no consigo contar un segundo exacto, al no saber exactamente como calcularlo segun la frecuencia del reloj (4 MHz) y los tiempos de cada instruccion.

Os dejo el codigo a continuacion:


Código: [Seleccionar]
#include <16F84A.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES XT                       //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#FUSES PUT                      //Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading

#use delay(clock=4000000)

#define TICKS 16
#define REFRESH_MS 3

void number(int num)  {
   output_low(PIN_B0);
   output_low(PIN_B1);
   output_low(PIN_B2);
   output_low(PIN_B3);
   output_low(PIN_B4);
   output_low(PIN_B5);
   output_low(PIN_B6);   
   switch(num)  {
      case 0:
         output_high(PIN_B0);
         output_high(PIN_B1);
         output_high(PIN_B2);
         output_high(PIN_B3);
         output_high(PIN_B4);
         output_high(PIN_B5);
         break;
      case 1:
         output_high(PIN_B1);
         output_high(PIN_B2);         
         break;
      case 2:
         output_high(PIN_B0);
         output_high(PIN_B1);
         output_high(PIN_B3);
         output_high(PIN_B4);     
         output_high(PIN_B6);   
         break;
      case 3:
         output_high(PIN_B0);
         output_high(PIN_B1);
         output_high(PIN_B2);
         output_high(PIN_B3);
         output_high(PIN_B6);         
         break;
      case 4:
         output_high(PIN_B1);
         output_high(PIN_B2);
         output_high(PIN_B5);
         output_high(PIN_B6);         
         break;
      case 5:
         output_high(PIN_B0);
         output_high(PIN_B2);
         output_high(PIN_B3);
         output_high(PIN_B5);
         output_high(PIN_B6);         
         break;
      case 6:
         output_high(PIN_B0);         
         output_high(PIN_B2);
         output_high(PIN_B3);
         output_high(PIN_B4);
         output_high(PIN_B5);
         output_high(PIN_B6);
         break;
      case 7:
         output_high(PIN_B0);
         output_high(PIN_B1);
         output_high(PIN_B2);         
         break;
      case 8:
         output_high(PIN_B0);
         output_high(PIN_B1);
         output_high(PIN_B2);
         output_high(PIN_B3);
         output_high(PIN_B4);
         output_high(PIN_B5);
         output_high(PIN_B6);
         break;
      case 9:
         output_high(PIN_B0);
         output_high(PIN_B1);
         output_high(PIN_B2);         
         output_high(PIN_B5);
         output_high(PIN_B6); 
       break;             
   } 

   delay_ms(REFRESH_MS);
}

void control(int place)  {
   switch(place)  {
      case 0:
     
         output_high(PIN_A0);
         output_high(PIN_A1);
         output_high(PIN_A2);
         output_high(PIN_A3);
         break;
      case 1:
 
         output_low(PIN_A0); 
         output_low(PIN_A1);
         output_low(PIN_A2);
         output_high(PIN_A3);
         break;
      case 2:
   
         output_high(PIN_A0);
         output_low(PIN_A1);
         output_low(PIN_A2);
         output_high(PIN_A3);
         break;
      case 3:
   
         output_low(PIN_A0);
         output_high(PIN_A1);
         output_low(PIN_A2);
         output_high(PIN_A3);
         break;
      case 4:
   
         output_high(PIN_A0);
         output_high(PIN_A1);
         output_low(PIN_A2);
         output_high(PIN_A3);
         break;
      case 5:
 
         output_low(PIN_A0);
         output_low(PIN_A1);
         output_high(PIN_A2);
         output_high(PIN_A3);   
   }         
}

void initialize(int u, int d, int c, int m, int d_m)
{
   control(1);
   number(u);   
         
   control(2);
   number(d);   
     
   control(3);
   number(c);   
     
   control(4);
   number(m);   
         
   control(5);
   number(d_m);   
}

void main()
{   
    int uni=0, dec=0, cen=4, mil=6, dec_mil=8;
int tick=0; 
   
    set_tris_a(0b00000000);       // Todas salidas A valor cero. Las entradas van con 1.
    set_tris_b(0b00000000);       // Todas salidas B valor cero. Las entradas van con 1.

    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256|RTCC_8_BIT);
    enable_interrupts(INT_TIMER0);
    enable_interrupts(GLOBAL);       
   
    while(1) {

      control(1);
      number(uni);   
      control(2);
      number(dec);   
      control(3);
      number(cen);   
      control(4);
      number(mil);
      control(5);
      number(dec_mil);

      if(T0IF) {                 
         tick++;
         T0IF=0; 

if(tick==TICKS-1) {

set_timer0(0xCB);
  }
     
         if(tick==TICKS) {

tick=0;
delay_us(555);
   
            if(dec_mil==0 && mil==0 && cen==0 && dec==0 && uni==0) {
uni=9; dec=9; cen=3; mil=6; dec_mil=8;
                initialize(uni,dec,cen,mil,dec_mil);
}
         
            else {

                  uni--;               
               
                  if(uni==-1) {
   
                  if(dec_mil==0 && mil==0 && cen==0 && dec==0)
                     uni=0;               
                 
                  else {       
                        uni=9;
                     dec--;
                     
                     if(dec==-1) {
     
                        if(dec_mil==0 && mil==0 && cen==0)
                           dec=0;
                        else {     
                              dec=9;
                           cen--;
     
                           if(cen==-1) {
                     
                              if(dec_mil==0 && mil==0)
                                 cen=0;
                              else {     
                                    cen=9;
                                 mil--;   
         
                                 if(mil==-1) {
           
                                    if(dec_mil==0)
                                       mil=0;
                                    else {       
                                          mil=9;
                                       dec_mil--;
           
                                       if(dec_mil==-1)       
                                             dec_mil=0;                     
                                    }
                                 }
                              }
                           }
                        }                                       
                     }                 
                  }                               
               }                 
            }             
          }         
       }
   }
}

Alguna idea de como calcular un segundo exacto?

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Imprecision en cuenta atras en tiempo real
« Respuesta #1 en: 12 de Agosto de 2013, 09:40:56 »
  No veo ninguna rutina de interrupción. Si tienes habilitadas las interrupciones, creo que debería existir una rutina para el manejo de las mismas. Ten en cuenta que cuando se genera una interrupción, el contador de programa salta a la posición 0x0004 (vector de interrupciones)

  Con el pic trabajando a 4MHz, el ciclo de instrucción es de 1us. Al configurar el divisor en 256, se te genera una interrupción cada 256us.

  Un posible problema es que en lenguaje C, no tienes un control exacto del tiempo ya que no sabes que instrucción de asm generará el compilador.

  Puedes compilar tu programa y simularlo en ISIS para ir contando el tiempo.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas


 

anything