[Ajuda] Utilizar Timer PIC16F877A

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

[Ajuda] Utilizar Timer PIC16F877A

Mensagempor marcosribeirobr » 29 Nov 2011 16:10

Olá galera não estou conseguir ajudar o timer do PIC16F877A, estou utilizando cristal de 4MHz e necessito que a cada 1 segundo seja incrementado a variável "segundo".

Segue o código até o momento, encontrei alguns exemplos de implementação do timer, mas acabou não dando certo.

Código: Selecionar todos

#define A_incre portd.f0
#define B_decre portd.f1
#define C_start portd.f2

char segundo, unidade_segundo, dezena_segundo, minuto;



//========================ATUALIZAÇÃO DISPLAY 7 SEGMENTOS=======================
void imprime_display (char posicao, char valor)
{
 portb=valor;
 if (posicao==1)        //UNIDADE SEGUNDO (CI4511 U3) PINO26
 {
  portc.f7=0;
  delay_ms(1);
  portc.f7=1;
 }
 else if (posicao==2)   //DEZENA SEGUNDO (CI4511 U2) PINO25
 {
  portc.f6=0;
  delay_ms(1);
  portc.f6=1;
 }
 else if (posicao==3)   //MINUTO (CI4511 U1) PINO24
 {
  portc.f5=0;
  delay_ms(1);
  portc.f5=1;
 }
}
//=======================FIM ATUALIZAÇÃO DISPLAY================================



//=========================ATUALIZAÇÃO DISPLAY TIMER============================
void imprime_timer (char posicao, char valor)
{
 portb=valor;
 if (posicao==1)        //UNIDADE SEGUNDO (CI4511 U3) PINO26
 {
  portc.f7=0;
  delay_ms(1);
  portc.f7=1;
 }
 else if (posicao==2)   //DEZENA SEGUNDO (CI4511 U2) PINO25
 {
  portc.f6=0;
  delay_ms(1);
  portc.f6=1;
 }
 else if (posicao==3)   //MINUTO (CI4511 U1) PINO24
 {
  portc.f5=0;
  delay_ms(1);
  portc.f5=1;
 }
}
//=======================FIM ATUALIZAÇÃO DISPLAY TIMER==========================



//================================TIMER 1=======================================
void interrupt()
{
 if (PIR1.TMR1IF)
 {
  segundo--;
  if (segundo==255)
  {
   minuto--;
   segundo=59;
  }
  dezena_segundo = segundo/10;
  unidade_segundo = segundo - segundo/10*10;
  imprime_timer (3,minuto);
  imprime_timer (2,dezena_segundo);
  imprime_timer (1,unidade_segundo);
  PIR1.TMR1IF = 0;              //reset timer1 flag
  TMR1L = 0xEC ;
  TMR1H = 0x78;
 }


}
//=============================FIM TIMER 1======================================



void main()
{
 trisa=0;
 trisb=0;
 trisc=0;
 trisd=0b11111111;
 porta=0;
 portb=0;
 portc=0;
 portd=0;
 
 minuto=0;
 segundo=0;

 
 while (1)
 {
 //============================BOTAO "A" INCREMENTO=============================
  while (A_incre==0)
  {
   if (minuto==9 && segundo==59)
   {
   }
   else
   {
    delay_ms (100);
    segundo++;
    if (segundo==60 && minuto<9)
    {
     minuto++;
     segundo=0;
     imprime_display (3,minuto);
    }
    dezena_segundo = segundo/10;
    unidade_segundo = segundo - segundo/10*10;
    imprime_display (3,minuto);
    imprime_display (2,dezena_segundo);
    imprime_display (1,unidade_segundo);
   }
  }
 //============================FIM INCREMENTO===================================
 
 //==========================BOTAO "B" DECREMENTO===============================
  while (B_decre==0)
  {
   if (minuto==0 && dezena_segundo==0 && unidade_segundo==0)
   {
    break;
   }
   else
   {
    delay_ms(100);
    segundo--;
    if (segundo==255 && minuto>0)
    {
     minuto--;
     segundo=59;
     imprime_display (3,minuto);
    }
    dezena_segundo = segundo/10;
    unidade_segundo = segundo - segundo/10*10;
    imprime_display (3,minuto);
    imprime_display (2,dezena_segundo);
    imprime_display (1,unidade_segundo);
   }
  }
 //============================FIM DECREMENTO===================================
 
 //========================BOTAO "START" CRONOMETRO=============================
  if (C_start==0)
  {
   T1CON.TMR1CS = 0;                    // Fosc / 4
   T1CON.T1CKPS1 = 1;                   // Setting prescale value to 1:8
   T1CON.T1CKPS0 = 1;                   //              "
   T1CON.TMR1ON = 1;                    //turn on timer1
   TMR1L = 0xEC ;
   TMR1H = 0x78;
   PIE1.TMR1IE = 1;
   PIR1.TMR1IF = 0;
   INTCON.PEIE = 1;
   INTCON.GIE = 1;           // Enable interrupt on overflow
  }
 
 
 //============================FIM CRONOMETRO===================================
 
 }//fim while (1)
}//fim void main
marcosribeirobr
Bit
 
Mensagens: 17
Registrado em: 27 Jul 2011 22:54
Localização: Brasil

Re: [Ajuda] Utilizar Timer PIC16F877A

Mensagempor andre_luis » 29 Nov 2011 19:48

marcosribeirobr escreveu:...Segue o código até o momento...mas acabou não dando certo.


O que acontece exatamente ?
Oscila fora da frequencia, ou sequer oscila ?


+++
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Re: [Ajuda] Utilizar Timer PIC16F877A

Mensagempor marcosribeirobr » 29 Nov 2011 20:27

andre_teprom escreveu:
marcosribeirobr escreveu:...Segue o código até o momento...mas acabou não dando certo.


O que acontece exatamente ?
Oscila fora da frequencia, ou sequer oscila ?


+++


Essa implementação do TIMER peguei em alguns exemplos na internet, mas nao deu certo pois está incrementando mais rápido que 1 segundo, tentei alterar os valores do TMR1L e TMR1H mas também não deu certo acabou piorando.
marcosribeirobr
Bit
 
Mensagens: 17
Registrado em: 27 Jul 2011 22:54
Localização: Brasil

Mensagempor ze » 30 Nov 2011 08:59

o mais legal seria se voce entendesse como funciona o circuito do timer antes de confiar cegamente no que acha na net. Que frequencia isso dá? confere se é 3.6Hz. neste caso ele é meio feio
Código: Selecionar todos
T1CON.T1CKPS1 = 1;                   // Setting prescale value to 1:8
 T1CON.T1CKPS0 = 1;                   //              "
 T1CON.TMR1ON = 1;                    //turn on timer1
 TMR1L = 0xEC ;
 TMR1H = 0x78;

façamos mais bunitinho 400Hz
TMR1L = 0xC8;
TMR1H = 0xFE;
eu poderia até saber explicar como cheguei nestes valores mas a parte legal é voce descobrir. Com este dado em mãos fica fácil ajustar 1 seg na interrupt
algo como:
Código: Selecionar todos
unsigned char segundo,minuto;
unsigned int tmp,seg=600; //p.ex. 10 minutos
void interrupt()
{
 if (PIR1.TMR1IF)
 {
  if (tmp++>399) {seg--;tmp=0;}
  minuto=seg/60;
  segundo=seg%60;
  dezena_segundo = segundo/10;
  unidade_segundo = segundo%10;
  imprime_timer (3,minuto);
  imprime_timer (2,dezena_segundo);
  imprime_timer (1,unidade_segundo);
...

dica: cristal de 1MHz no clock voce deve conseguir menor freq na interrupt ou se voce colocar cristal 32768 externo no timer1
li rápido o dshit e pode haver alguma shit e claro desconsidere as palavras acima pois não deve confiar na net, lembra?
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Mensagempor marcosribeirobr » 30 Nov 2011 15:48

lellis escreveu:o mais legal seria se voce entendesse como funciona o circuito do timer antes de confiar cegamente no que acha na net. Que frequencia isso dá? confere se é 3.6Hz. neste caso ele é meio feio
Código: Selecionar todos
T1CON.T1CKPS1 = 1;                   // Setting prescale value to 1:8
 T1CON.T1CKPS0 = 1;                   //              "
 T1CON.TMR1ON = 1;                    //turn on timer1
 TMR1L = 0xEC ;
 TMR1H = 0x78;

façamos mais bunitinho 400Hz
TMR1L = 0xC8;
TMR1H = 0xFE;
eu poderia até saber explicar como cheguei nestes valores mas a parte legal é voce descobrir. Com este dado em mãos fica fácil ajustar 1 seg na interrupt
algo como:
Código: Selecionar todos
unsigned char segundo,minuto;
unsigned int tmp,seg=600; //p.ex. 10 minutos
void interrupt()
{
 if (PIR1.TMR1IF)
 {
  if (tmp++>399) {seg--;tmp=0;}
  minuto=seg/60;
  segundo=seg%60;
  dezena_segundo = segundo/10;
  unidade_segundo = segundo%10;
  imprime_timer (3,minuto);
  imprime_timer (2,dezena_segundo);
  imprime_timer (1,unidade_segundo);
...

dica: cristal de 1MHz no clock voce deve conseguir menor freq na interrupt ou se voce colocar cristal 32768 externo no timer1
li rápido o dshit e pode haver alguma shit e claro desconsidere as palavras acima pois não deve confiar na net, lembra?


Primeiramente obrigado pela ajuda, esqueci de mencionar no inicio do post que sou leigo no assunto e peço desculpa pela minha ignorância em alguns comentários..rsrs pois tudo é novo ainda para mim ainda, quanto ao TIMER se puder explicar como chegou nos resultados obtidos ficarei grato pois também não consegui chegar no valor.

Desde já, agradeço.
marcosribeirobr
Bit
 
Mensagens: 17
Registrado em: 27 Jul 2011 22:54
Localização: Brasil

Mensagempor MOR_AL » 30 Nov 2011 17:30

Olá!
Você está ciente de que o contador do TIMER é incrementado a cada pulso de clock, e portanto o tempo de contagem é "quanto falta" para a contagem "virar" de tudo um para tudo zero?
Tente ler o manual que lá tem toda a informação necessária para programá-lo.
Se o seu inglês não for suficiente, tem documentação em português na net.
Bons projetos.
MOR_AL
"Para o triunfo do mal só é preciso que os bons homens não façam nada." Edmund Burke.
"Nunca discutas com pessoas estúpidas. Elas irão te arrastar ao nível delas e vencê-lo por possuir mais experiência em ser ignorante". Mark Twain
Avatar do usuário
MOR_AL
Dword
 
Mensagens: 2934
Registrado em: 19 Out 2006 09:38
Localização: Mangaratiba - RJ

Mensagempor ze » 01 Dez 2011 07:27

pois não amigo. presuponho que já tenhas noção de hexadecimal <-> decimal, MegaHerts, MSB, LSB e afins. Caso não tenha não temas adimitir. Aprenda e releia depois.
faço minha as palavras do moris. vejamos se consigo exemplificar. veja o circuito do timer
Imagem
ao ligar TMR1CS=0 note que vai entrar 1MHz no prescaler que voce programou para dividir por 8
1Mhz=1000000Hz isto implica que 1000000/8=125000Hz. memorize
Só que eu quero 400Hz de interrupção. Lembra do 125000 laaaaá de trás? Portanto 125000/400=312,5 (numero quebrado não é bom. fda-se, por enquanto)
De acordo com a teoria 'do moris' (vulgo MOR_AL) a interrupção ocorre quando o contador - que é crescente - passa de 0xffff para 0x0000 ou seja no momento 65536 (ou é 65535...? nunca sei). Portanto para passar por isso a 400 ciclos por segundo (Hz) ele precisa de 312,5 contagens (num falei que não era um bom numero?). Devemos fazer 65536-312,5=65223,5. Esquecendo o 0,5 em hexa fica 0xfe7c que é o que deve ser carregado no timer1 TMR1H=0xfe TMR1L=0x7c (recarga)

(putz! agora o valor deu diferente. antigamente eu era confuso, hoje em dia não tenho mais certeza. veja a mecânica da coisa aí pelo menos. to com pregui de rever os calculos.)


Exercício:
mostre que voce entendeu e calcule os valores de recarga para prescaler = 4 sendo essa a primeira coisa a fazer na interrupção

abç
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32


Voltar para PIC

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

cron

x