Ir ao conteúdo
  • Cadastre-se
Iury Messias

Leitura de frequência com pic 18f877a

Recommended Posts

Olá amigos do Clube do Hardware, estou desenvolvendo um pequeno projeto para realizar a leitura de frequência por meio do modulo CCP e de um LCD, utilizando o PIC 16f877a, no layout que montei no ISIS uma label HDL gera um pulso de 5000us(2500us em nivel baixo e 2500us em nivel alto) na entrada ccp1 do microcontrolador, o microcontrolador esta configurado para setar o registrador CCP_1 a cada quatro bordas de subida.
O problema com qual me deparei é na hora de mostrar o valor da frequência no LCD, o período apareceu sem problema algum, mas a frequência apresenta 0 .
O código que estou utilizando no CCS é o seguinte :

 

#include <16f877a.h>
#fuses NOWDT, PUT, NOLVP
#use delay(clock=4000000)
#include <lcd.c>
unsigned int16 ps=0; //Guarda a leitura da primeira comparação com 4 pulsos de subida
unsigned int16 ss=0; //Guarda a leitura da segunda comparação com 4 pulsos de subida
int1 pulso=0; //Controla em que momento acontece a captura
int1 trocapulso=0; //Utilizada para visualizaão do periodo que esta na variavel tempo
#INT_CCP1
void CCP1_isr(void)
{
   if(pulso==0) //Primeira captura
   {
      ps=CCP_1; //O valor da primeira captura é guardado em ps
      pulso=1; //Muda para captura depois de 4 bordas de subida 
   }else
      {
         ss=CCP_1; //A segunda captura depois de 4 bordas de subida é guardada em ss
         pulso=0; //Muda para 0 para poder realizar uma primeira leitura
         if(trocapulso==0)      //Quando realiza a segunda captura depois de 4 bordas de subida
         {             //Troca-se o valor desta variavel auxiliar
            trocapulso=1;  //Para utilizar na visualização do valor do periodo da onda quadrada
         }
      }

}
void main()
{
   
   unsigned int16 tempo=0;//Variavel que guardara diferença de tempo entre SS e PS
   int frequencia;
   setup_timer_2(T2_DIV_BY_4,255,1); // tmr2 com prescaler de 4 contagem até 255 e potscaler 1:1(255 , 1)
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
   setup_ccp1(CCP_CAPTURE_DIV_4); //Modo ccp1 4 bordas de subida
   enable_interrupts(INT_CCP1);
   enable_interrupts(INT_TIMER2);
   enable_interrupts(GLOBAL);
   lcd_init();
   set_timer1(0);
   
   while(true)
   {
      if(trocapulso==1)
      {
         disable_interrupts(GLOBAL); //Desabilita as interrupções para ler valor no LCD
         
         tempo=(ss-ps); //Tempo recebe ss-ps que são os valores capturados nas interrupções
         tempo=tempo/4;
            
         
         lcd_gotoxy(1,1);
         delay_us(40);
         printf(lcd_putc,"Periodo %lu us",tempo); // A variavel tempo se divide em 4 porque se passaram 4 peridos no processo de captura
         delay_ms(100);
        
         frequencia=((float)1/(ss-ps));
         
         lcd_gotoxy(2,2);
         printf(lcd_putc,"Freq. %d HZ",frequencia);
         delay_us(40);
         
         
         
         
         
         trocapulso=0;  //Muda o valor da variavel para obter novas capturas
         enable_interrupts(GLOBAL); // Uma vez visto o periodo no lcd ativa-se as interrupções
      }
   }

}

Estou anexando uma imagem do ISIS.
Se puderem me ajudar a solucionar  aonde estou errando é como, eu ficarei muito agradecido.

ISIS.jpg

Compartilhar este post


Link para o post
Compartilhar em outros sites

Numa análise superficial notei isso...

15 horas atrás, Iury Messias disse:

frequencia=((float)1/(ss-ps));

Se (ss-ps)=0 vai cataclismar o universo. E se não for, o resultado de frequencia sempre vai ser 0 pois ela é unsigned int

-float e mc 8 bits não se dão muito bem. Mc de 8 bits trabalha em seu âmago em binário. você já ouviu falar em lógica binária fracionária? pois é.. nem eu.

 

15 horas atrás, Iury Messias disse:

printf(lcd_putc,"Freq. %d HZ",frequencia);

 

-Não sei se %d é a correta formatação para float (mesmo sendo, a variável não é)

-printf é bem guloso. Talvez você deva formatar com sprintf ou algo do gênero. Mas de novo, rotinas gulosas. 

Tente p.ex. fazer

float frequencia;

frequencia=(float)(1.000/((float)ss-(float)ps));

e depois formatar com sprintf ou colocar o argumento correto no printf do display

Seu compilador deve xiar e deve ocupar quase a metade da memória do seu mc

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Isadora Ferraz de antemão peço desculpas pois digitei "Fernanda" no outro post quando era "Isadora" :D, mas creio que achei a solução, reanalisando o código eu observei que fiz uma tempestade dentro de um copo d'água pois, declarando a variável frequência como int16 o código que antes estava:

 

frequencia=((float)1/(ss-ps));

 

pode ser substituído por :

 

frequencia= 1000000/tempo;

 

dai a saída fica :

 

 printf(lcd_putc, "Freq. %lu HZ",frequencia);

 

dando o resultado correto da frequência e utilizando 8% da memoria :D

 

Muito obrigado pela ajuda.

 

.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora





Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×