Programa para medir freqüência com PIC...(ajuda)
 Mosaico
 Mosaico
 PIC
 Programa para medir freqüência com PIC...(ajuda)
  Registrar   Ajuda   Login

Tópico AnteriorTópico Anterior - Próximo TópicoPróximo Tópico
Tópico com 5801 visitas e 14 mensagens
Autor
Tópico: Programa para medir freqüência com PIC...(ajuda)
Smarley
Usuário Nivel 4

Postagens: 40
Registro: 16/07/2008
Local: - - BrasilSexo não informado
 Postado em 16/07/2008 11:33:00 PM

Eu precisava fazer um programa para ler freqüência e mostrar em um dysplay lcd.
Só que eu não estou conseguindo.
Pelo livro que eu estava lendo, o PIC tem os timer`s e pensei que com eles eu conseguisse ler a ferquencia, mas n deu certo.

O programa que escrevi é este, tirado de um livro para ligar e desligar 1 led a cada 1 segundo.

--------------------------------------------------------------------------

#include<16f877a.h>
#use delay(clock=4000000)
#fuses HS,NOWDT,PUT,NOLVP

#int_timer0
void trata_t0()
{
static boolean led;
static int conta;

set_timer0(131 + get_timer0());
conta++;
if(conta == 125)
{
conta=0;
led=!led;
output_bit(PIN_A1,led);
}
}
main()
{
setup_timer_0 (RTCC_INTERNAL | RTCC_DIV_64 );
set_timer0(131);
enable_interrupts (global | int_timer0);
while (true);
}


--------------------------------------------------------------------------

Este programa funcionou beleza, só que o que eu tinha pensado era em colocar um:
if(input(PIN_A1))
{
x++;
}
antes daquele if(conta==125), para cada vez que ele ler o pin_a1 e ele estiver ligado ele contasse 1 a mais no x.
Só que o que acontece é que ele le no máximo 125 vezes, pois eh a quantidade de vezes que o laço roda até contar 1 segundo.
Ou seja, eu precisaria ler muito mais vezes que isto.

Eu não sei se estou usando o tipo de programa certo, por isso postei aki.

Eu gostaria de alguma dica, de como melhorar este, ou de outro tipo de programa, que faça esta contagem.
Eu não conheço nenhum recurso do PIC, mas seria interessante se ele tivesse uma contagem paralela sempre. Eu achei que ele tivesse algo como:
while(timer<=1); para quando o tempo for igual ou menor que 1segundo.
Era mais ou menos isso que eu precisava, para ficar lendo uma porta dentro deste laço.


IP LogadoPróxima Mensagem
jsbrown
Usuário Nivel 5

Postagens: 433
Registro: 08/05/2008
Local: - MG - Brasil
Idade: 85 anosSexo Masculino
 Postado em 17/07/2008 11:53:00 AM

oi. medir freq é relativamente simples. 1 maneira é usar os recursos de hw do pic. ex bem simplista:
com uma interrupçao do timer 0 a cada segundo e com a entrada do sinal no timer 1. dentro da interr é só capturar os registros TMR1H e TMR1L que já é o valor direto em hz. Na saída da interr, zerar o timer 1. É claro com este artifício só vai medir até 65535 Hz. Pra freq maiores use o prescaler. Pra maiores ainda, use prescaler externo - um 74F192 p.ex.
Nada de while() fazendo o uC perder tempo a toa.
Se usar uma base de tempo menor tende a ficar + eficaz.
Obs: tente primeiro entender os timers do pic. é simples!!!
abrçs

IP LogadoMensagem AnteriorPróxima Mensagem
Smarley
Usuário Nivel 4

Postagens: 40
Registro: 16/07/2008
Local: - - BrasilSexo não informado
 Postado em 17/07/2008 1:43:00 PM

Eu entendi o que tu quiz dizer, mas não entendi como fazer.
Eu tentei assim.
O meu timer0 está certo, contando a cada 1 segundo:

int x,y;
#int_timer0
void trata_t0()
{
int conta;
set_timer0(131+get_timer0());
conta++;
if(conta==125)
{
conta=0;
y=x;
x=0;
}
}

E o timer1 esta funcionando 65535 vezes:

#int_timer1
void trata_t1()
{
int conta;
set_timer1(get_timer1());
conta++;
if(input(PIN_A0))
{
x++;
}
if(conta==65535)
{
conta=0;
}
}

Pelo que eu entendi e fiz, seria o seguinte. O timer1 estaria rodando de 0 a 65535, e contando o x. A cada seguno que se passasse no timer0, ele iria guardar o valor de x em y, e zerar o x, para começar um nova contagem no timer1.
É isso mesmo que eu entendi?
Os 2 timers funcionam simultaneamente?

O main está aki:

void main()
{
lcd_init();
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64);;
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(global|int_timer0|int_timer1);
set_timer0(131);
while(true);
}

Com esta linha assim: enable_interrupts(global|int_timer0|int_timer1); ele não funciona nem o timer0, nem o timer1. Se eu coloco assim: enable_interrupts(global|int_timer0&&int_timer1); ele funciona o timer0, mas o 1 não, Eu não sei o que esta acontecendo mas o 1 não esta contando.

O que eu teria que mudar no programa??

Lembro que não tenho experiência com PIC, estou começando agora, e não sei mutia coisa sobre C. Apenas o que aprendo nos livros. Toda ajuda será bem-vinda.

abraço, e obrigado pela ajuda!

IP LogadoMensagem AnteriorPróxima Mensagem
jsbrown
Usuário Nivel 5

Postagens: 433
Registro: 08/05/2008
Local: - MG - Brasil
Idade: 85 anosSexo Masculino
 Postado em 17/07/2008 3:33:00 PM

vamo tentá fazê só por hw. óia só:

unsigned int freq; //variável que captura a freq...dããããã
timer0interr() //trata a interrupção
{
...
...//importante:restaurar os valores do timer e flag (TMR0IF acho)
...
freq=TMR1H*256+TMR1L;
TMR1H=TMR1L=0; //zera pra nova captura
}

main()
{
...
...
//configurar o tm0 pra interr a 1 seg já conseguiu?? vamo pulá..
...
//configurar o timer1 pra clock externo
//vindo do data sheet:
T1CKPS1=0;T1CKPS0=0; //sem prescaler
T1OSCEN=0;//inibe osc externo
TMR1CS=1;//o sinal vem por fora no pino T1CKI: o pulo do gato!!
TMR1ON=1;//habilita o danado
...
...
for(;;)
{
printlcd(freq); //zefini...
}
}

de novo, dá uma olhadinha no datashit e veja a função de cada bit acima que entenderás...
abrçs & boasorte!!!!!!!!


IP LogadoMensagem AnteriorPróxima Mensagem
Smarley
Usuário Nivel 4

Postagens: 40
Registro: 16/07/2008
Local: - - BrasilSexo não informado
 Postado em 17/07/2008 4:41:00 PM

Fui no datasheet e li a função destas operações...
Agora eu entendi o que tu quiz dizer desde o princípio.
Tu fala para eu usar a interrupção do timer0 e contar de 1 em 1 segunda, e usar o timer 1 como se fosse receber a frequencia de um crystal externo.
No caso, eu não precisarei de nenhuma função para o timer1 seria somente eu pegar esta frequencia e gravá-la a cada segundo em uma variável.

Ai para montar a frequencia eu entendi, tu desloca o TMR1H 8 bits para a esquerda, multiplicando por 256 e soma com a parte baixa, TMR1L.

Só que o problema está acontecendo no seguinte.
Eu estou usando o CCS Compiler para fazer o programa, e ele não reconhece estas expressões do datasheet.
Ainda estou tentando descobrir como tratar delas no CCS...

IP LogadoMensagem AnteriorPróxima Mensagem
Smarley
Usuário Nivel 4

Postagens: 40
Registro: 16/07/2008
Local: - - BrasilSexo não informado
 Postado em 17/07/2008 9:54:00 PM

Descobri como faz!
é o seguinte, é soh usar a expressão, get_timer1(); eu fiz assim:
unsigned long int freq;
freq=get_timer1();

agora eu ja consigo alocar ela, mas não funcionou ainda, não sei o q pode estar acontecendo...

IP LogadoMensagem AnteriorPróxima Mensagem
Smarley
Usuário Nivel 4

Postagens: 40
Registro: 16/07/2008
Local: - - BrasilSexo não informado
 Postado em 17/07/2008 10:08:00 PM

Problema resolvido abaixo segue todo o código para quem quiser:


Tive que dividir a freqüência por 2 para dar certo.

#include "C:\Arquivos de programas\PICC\timer0.h"


#define LCD_ENABLE_PIN PIN_B0
#define LCD_RS_PIN PIN_B1
#define LCD_RW_PIN PIN_B2
#define LCD_TYPE 2
#include <lcd.c>

unsigned long int freq;
#int_timer0
void trata_t0()
{
int conta;
boolean led;
set_timer0(131+get_timer0());
conta++;
if(conta==125)
{
freq=get_timer1();
led=!led;
output_bit(PIN_D1,led);
conta=0;
set_timer1(0);
}
}

void main()
{
lcd_init();
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64);;
setup_timer_1(T1_EXTERNAL_SYNC|T1_DIV_BY_1);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_RTCC);
enable_interrupts(INT_EXT);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
set_timer0(131);
set_timer1(0);
enable_interrupts(global);
enable_interrupts(int_timer0);
enable_interrupts(int_timer1);

while(true)
{
freq=freq/2;
printf(lcd_putc,"\f freq = %lu",freq);
delay_ms(1000);
}

}

IP LogadoMensagem AnteriorPróxima Mensagem
LUMENS-TEL
Usuário Nivel 5

Postagens: 293
Registro: 07/04/2003
Local: Charqueada - SP - Brasil
Idade: 49 anosSexo Masculino
 Postado em 27/08/2008 11:19:00 AM

Olá Smarley
tentei usar seu exemplo em pic 628a.
simulei com o proteus, coloquei um sinal 60hz/6v na pino RB6
porem não apareceu a frequencia no display
aparece como frequencia=0.

#include <16f628a.h>
#use delay(clock=4000000)
#fuses HS,NOWDT,PUT,NOLVP
#include <timer0.h>
#include <mod_lcd.c>
unsigned long int freq;
#int_timer0
void trata_t0()
{
int conta;
boolean led;
set_timer0(131+get_timer0());
conta++;
if(conta==125)
{
freq=get_timer1();
led=!led;
output_bit(PIN_a1,led);
conta=0;
set_timer1(0);
}
}

void main()
{
lcd_ini();

setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64);;
setup_timer_1(T1_EXTERNAL_SYNC|T1_DIV_BY_1);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_RTCC);
enable_interrupts(INT_EXT);
enable_interrupts(int_timer0);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
set_timer0(131);
set_timer1(0);


while(true)
{
freq=freq/2;
printf(lcd_escreve,"\f freq = %lu",freq);
delay_ms(1000);
}

}


IP LogadoMensagem AnteriorPróxima Mensagem
_newman_
Usuário Nivel 5

Postagens: 226
Registro: 09/10/2007
Local: - - BrasilSexo Masculino
 Postado em 29/08/2008 11:17:00 AM

Smarley

não precisa de nenhum componente externo ao pic?

abrax!

IP LogadoMensagem AnteriorPróxima Mensagem
LUMENS-TEL
Usuário Nivel 5

Postagens: 293
Registro: 07/04/2003
Local: Charqueada - SP - Brasil
Idade: 49 anosSexo Masculino
 Postado em 29/08/2008 8:06:00 PM

Mensagem original postada por _newman_ Smarley

não precisa de nenhum componente externo ao pic?

abrax!


em relação ao proteus vc quiz dizer? com o proteus usei um gerador de sinal ac com amplidude de 6V/60Hz.

IP LogadoMensagem AnteriorPróxima Página
 Todos os horários são de Brasília (GMT -03:00)
 Nova Mensagem desde a sua Última Visita.
[***] Palavra proibida pelo moderador do Grupo de Discussão
Páginas: 1 2
Tópico AnteriorTópico Anterior - Próximo TópicoPróximo Tópico

Volta para o Topo da Página



Forum Now! - Criar seu forum grátis