Ir ao conteúdo
  • Cadastre-se

Timer1 impreciso (external)


Posts recomendados

Bom dia pessoal do CDH, seguinte, estou desenvolvendo um projeto onde haverá um relógio de tempo real, onde o contador será o timer1 com oscilador externo ( um cristalzinho de 32768) ligado no T1OSI e no T1OSO, pinos C0 e C1 do pic 16F876A, dessa forma a cada 1 segundo ocorre o estouro do timer fazendo uma variavel booleana mudar de estado.

 

Na rotina principal, dentro do while, tenho um comando para exibir o tempo no display 16x2, e nele não contem nenhum delay.

 

função de tratamento do timer1:

#int_TIMER1void  TIMER1_isr(void) {           tck=true;set_timer1(60768);}

Laço while principal:

lcd_gotoxy (1,1);printf(lcd_putc," SISTEMA PRONTO");lcd_gotoxy (1,2);printf(lcd_putc,"    %02u:%02u:%02u"hh,mm,ss);

If comparador da variavel tck:

if(tck==true) //Se tck = true (ocorreu o tempo de 1 segundo)         {            ss++; //Incrementa a variável sec               if (ss>59) //Se a variável sec > 59                  {                     ss=0; //Faz sec = 0                     mm++; //Incrementa a variável min                        if(mm>59) //Se a variável min > 59                           {                              mm=0; //Faz min = 0                              hh++; //Incrementa a variável hour                                 if(hh>23)                                  {                                     hh=0; //Se hour > 23, faz hour = 0                                                                       }                           }                  }                 tck=false; //Faz tck = false;         }

O circuito está montado em uma protoboard.

 

Ocorre que ontem por volta das 16:00hs acertei o relógio com o relógio do meu celular, e hoje por volta das 8:00hs deu uma diferença de 40 min, praticamente 16 horas depois o relógio do circuito estava 40 minutos adiantado em relação ao relógio do meu celular.

 

o que pode ter de errado??

 

Att.

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Foi melhor assim. Relógio que atrasa não ia adiantar mesmo. Cara que viagem ... no tempo (af trocadilho sem graça)

 

Este é um dos problemas de confiar cegamente nas libs mastigadas deste compilador. Não se sabe o que está ocorrendo nas entranhas do mc. Mas enfim, é o que você tem.

Descartando problemas de hw (cristal, capacitores e tal) tente fazer microajustes tipo alterando o argumento do settimer e/ou micro-ajustando com asm("nop") e tal.

 

Aliás, existe cristal 32768 de 6 e de 12pF sabia? Olhando pra eles são idênticos e esquece, não tem como medir esta capacitância. Sim, ela dá diferença.

abç

Link para o comentário
Compartilhar em outros sites

Bom.

Porque você escolheu a contagem inicial do TIMER1 com 60768?

Ele vai estourar a contagem com 65.536.

Então vai contar 65.536 - 60.768 = 4.768.

Com um clock de 32768 haverão 32.768 / 4.768 = quase 7 interrupções por segundo.

 

Me corrijam se estiver errado, mas você tem que escolher a contagem inicial do TIMER1 com

65536 - 32768 = 32.768

Assim o TIMER1 vai estourar a contagem a cada segundo.

Além disso, você ainda terá que compensar o tempo que leva para você renovar o valor do TIMER1 desde o estouro, até sua efetiva renovação.

Algo como

set_timer1(32.768 - get_timer1()) Deve ser algo assim, não estou familiarizado com C.

MOR_AL

Link para o comentário
Compartilhar em outros sites

Bom.

Porque você escolheu a contagem inicial do TIMER1 com 60768?

Ele vai estourar a contagem com 65.536.

Então vai contar 65.536 - 60.768 = 4.768.

Com um clock de 32768 haverão 32.768 / 4.768 = quase 7 interrupções por segundo.

 

Me corrijam se estiver errado, mas você tem que escolher a contagem inicial do TIMER1 com

65536 - 32768 = 32.768

Assim o TIMER1 vai estourar a contagem a cada segundo.

Além disso, você ainda terá que compensar o tempo que leva para você renovar o valor do TIMER1 desde o estouro, até sua efetiva renovação.

Algo como

set_timer1(32.768 - get_timer1()) Deve ser algo assim, não estou familiarizado com C.

MOR_AL

Bom.

Porque você escolheu a contagem inicial do TIMER1 com 60768?

Ele vai estourar a contagem com 65.536.

Então vai contar 65.536 - 60.768 = 4.768.

Com um clock de 32768 haverão 32.768 / 4.768 = quase 7 interrupções por segundo.

 

Me corrijam se estiver errado, mas você tem que escolher a contagem inicial do TIMER1 com

65536 - 32768 = 32.768

Assim o TIMER1 vai estourar a contagem a cada segundo.

Além disso, você ainda terá que compensar o tempo que leva para você renovar o valor do TIMER1 desde o estouro, até sua efetiva renovação.

Algo como

set_timer1(32.768 + get_timer1()) Deve ser algo assim, não estou familiarizado com C.

Mesmo assim ainda haverá algum erro.

MOR_AL

@MOR me perdoe pela falha.. o numero certo que estou usando é realmente 32768, é que pra simular a uma velocidade mais rapida alterei este valor e na hora de postar não voltei ao normal..

 

Desculpa ai a falha.. acho que no momento do post estava com a cabeça na lua hehe

 

vou testar sua sugestão aqui...

Link para o comentário
Compartilhar em outros sites

Você tem dois caminhos (que eu me lembre) para obter precisão.

 

1 - Usar um kit RCT

https://www.google.com.br/search?q=real+clock+timer&também=isch&imgil=Z_7zQWDnNXbALM%253A%253BH57OTk0DvZEgQM%253Bhttp%25253A%25252F%25252Fwww.intersil.com%25252Fproducts%25252FISL1208.html&source=iu&pf=m&fir=Z_7zQWDnNXbALM%253A%252CH57OTk0DvZEgQM%252C_&usg=__1DM_Ut8gbNn8TjOcmY8MD1gf8lA%3D&biw=1293&bih=882

 

Esta opção possui a vantagem de incluir uma bateria, que não desliga o timer quando se desliga o aparelho. Semelhante ao PC.

 

2 - Usar linguagem Assembler no tratamento da interrupção e renovação do valor do TIMER1.

Assim você poderia contar quantas instruções existiriam e descontar o valor (somar) no TIMER1. Não precisaria nem de cristal extra, apenas o do microcontrolador. Mas daria um bom trabalho.

 

Em tempo:

Salvei a postagem anterior, mas não apareceu o conteúdo salvo. Salvei outra vez e ocorreu o mesmo problema. Depois acessei o tópico e observei que havia a resposta e uma repetição do comentário. Tive que editar depois. Você sacou mais rápido e ainda pegou a resposta duplicada.

 

MOR_AL

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

voce pode melhorar a precisaão da rotina assim:

set_timer1 (XXXXX - get_timer1());

Onde XXXXX é o valor a recerragar.

 

Analise o asm que o acima gera. Depois tente acessar direto o hw com algo assim (caso o compilador permita)

TMR1H=0x80; //32768TMR1L=0x00;

E compare não só a a precisaão como eficiência do código

E você pode fazer um relógio só incrementando uma variável "segundo" a cada segundo (dãããmmm)

algo tipo assim (depois eu confiro)

hora=segundo%3600;minuto=segundo%60;

abç

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...