Ir ao conteúdo
  • Cadastre-se

Leitura de frequência com pic 18f877a


Posts recomendados

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

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

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

 

Link para o comentário
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.

 

.

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades 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

×
×
  • Criar novo...

 

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!