Anúncios

01/11/2012

Utilizando o TIMER0 do PIC

Utilizando o TIMER0 do PIC

O TIMER0 normalmente é utilizado em projetos para fazer a base de tempo, ou seja, o relógio do projeto, como contar tempo para repetir ou considerar um evento.

O TIMER0 utiliza normalmente três registros especiais (SFR), dependendo do PIC a ser utilizado. Mostrarei como utilizar o TIMER0 do PIC16F877A.








PIC16F877A

O temporizador/Contador TIMER0 possui as seguintes características:

• temporizador/contador de 8 bits;
• leitura e gravação;
• software prescaler de 8 bits programável;
• Relógio interno ou externo selecionavel;
• Interrupção no estouro de FFh para 00h;
• Borda de seleção para relógio externo;

Registros associados ao TIMER0:




MODO CONTADOR:

O TIMER0 funciona como contador, quando você usa como oscilador os pulsos externos aplicado no pino RA4/T0CKIN.

Você deve configurar o seguinte registro:





T0CS - Define a fonte de clock do TIMER0:

1 - Externa (PINO RA4/T0CKIN) - Modo contador;
0 - Interna (Cristal de quartzo) - Modo temporizador;


T0SE - Seleção da borda de transição do pino RA4/T0CKIN

1 - transição nivel alto-baixo (transição negativa);
0 - transição nivel baixo-alto (transição positiva);


PSA - Habilitação do prescaler (no modo CONTADOR é comum desabilitar);


1 - Desabilitado;
0 - Habilitado;



PS2, PS1, PS0 - Seleção do prescaler( somente no modo temporizador);


   bits / TMR0 rate
000 1:2
001 1:4
010 1:8
011 1:16
100 1:32
101 1:64
110 1:128
111 1:256



Exemplo:

void main()
{
TRISB=0;
OPTION_REG=0b10111000; //modo contador
TMR0=0;                   //Inicializa o registro TMR0 com o valor 0.
while(1)
{
  if(INTCON.TMR0IF)
  {
     INTCON.TMR0IF=0;    //limpa a flag
     TMR0 = 0; 
     portb=~portb; //quando acontecer o overflow(a cada 256 pulsos) interver as saidas
  }
delay_ms(10);
}
}




O registro TMR0 é o registro que armazena o estado inicial da contagem. Possui 8 bits, por  isso conta de 0 a 255. Quando acontece o overflow ele retorna a contagem inicial 0. O bit do overflow é o INTCON.TMR0IF e deve ser limpo por software.

MODO TEMPORIZADOR:

O temporizador do TIMER0 funciona quando você usa o oscilador interno do PIC ou o cristal de quartzo externo.

Você deve configurar os seguintes bits do registro OPTION_REG:


T0CS - Define a fonte de clock do TIMER0:
1 - Externa (PINO RA4/T0CKIN) - Modo contador;
0 - Interna (Cristal de quartzo) - Modo temporizador;

PSA - Habilitação do prescaler (no modo CONTADOR é comum desabilitar);

1 - Desabilitado;
0 - Habilitado;



PS2, PS1, PS0 - Seleção do prescaler;


bits / TMR0 rate
000 1:2
001 1:4
010 1:8
011 1:16
100 1:32
101 1:64
110 1:128
111 1:256


Você deve estar perguntando: O que é prescaler?
Prescaler é o divisor de frequência do clock do TIMER0. É usado no modo temporizador para poder obter tempos maiores.





A fórmula do tempo para o overflow é a seguinte:

t = ciclo de máquina * prescaler * contagem ( 256 - TMR0 );

ciclo de máquina = 4 / Fosc;


Fosc é a freqência do clock do cristal oscilador.

EXEMPLO:
O clock de um PIC é de 4MHz, utlizado o prescaler de 1:256 e contagem de 0 a 256, qual será o tempo?

ciclo de máquina = 4/4 = 1us.

t = 1 * 256 * 256;
t = 65536us ou 65,536ms

para ter tempos ainda maiores, como alguns segundos,um dos meios de se conseguir é utilizando a interrupção.
Veja um exemplo: utilizando clock 4Mhz e prescaler de 1:4.

unsigned contagem;

void interrupt()
{ 
contagem++;       //para cada interrpção do TMR0 incrementa a variável contagem
TMR0 = 0; 
INTCON.TMR0IF = 0;  //limpa o overflow.
}

void main()
{
INTCON.GIE = 1; //habilita interrupção global;
INTCON.PEIE = 1; //habilita interrupção dos perifericos;
INTCON.TMR0IE = 1; //habilita interrupção do TMR0;
TMR0 = 0; // TIMER0 inicia com o valor 0;
OPTION_REG = 0b10000001; // Modo Temporizador, prescaler 1:4;
//tempo =1us * 4 * 256 = 1ms
...
while (1)
{
   if(contagem == 1000)    //quando o contagem = 1000, tempo = 1000 * 1ms = 1s;
   {
     portb.RB0 = ~portb.RB0;  //inverte o estado do pino rb0
     contagem = 0; //reseta a variavel contagem 
   }                     
}
}


58 comentários:

  1. Boa tarde.
    No texto você coloca t=65,536ms e no código 4,096ms
    É uma divisão por 16 que eu não consegui entender.
    Outra coisa, preciso contar um segundo com um cristal de 20MHz, pode me ajudar na conta mais precisa /

    ResponderExcluir
    Respostas
    1. Muito obrigado pelo seu comentário! É o primeiro do blog!!!
      Você tem razão,acabei utilizando o prescaler de 1:256 sendo que na verdade é de 1:16, me desculpe pelo erro e já corrigi.

      No seu caso:
      ciclo de máquina = 4 / 20MHZ = 0,2 us.

      tempo = 0,2 * 4 * 125 = 100us.
      utilizando prescaler de 1:4 e TMR0=131(256 - 125) => irá contar de 131 a 256.

      Para cada interrupção gerada, você pode incrementar uma variável (x) e quando essa variável chegar no valor de 10000 executar alguma coisa.
      No final de tudo: 10000 * 100us = 1segundo.

      Espero que possa ter entendido! Muito obrigado pelo seu comentário!!

      Excluir
  2. Boa tarde,

    Primeiramente gostaria de lhe dar os parabéns pela explicação, pesquisando, não encontrei nada nem mesmo similar. Muito bom!!!

    Infelizmente não estou entendendo muito bem a configuração do "optionreg" já li e reli o datasheet do pic16f877a mas ainda tenho duvidas sobre como delarar as variáveis do pre escale.

    Estou tentando fazer um led piscar com a funçar timer0, você poderia me auxiliar?

    ResponderExcluir
  3. Obrigado :)

    Cada bit do registro OPTION_REG tem uma função. os bits 2, 1 e 0 possui a função de configurar o prescaler. Então, caso OPTION_REG = 0B10000111, como os ultimos bits são 111, o prescaler será 1:256.

    para poder fazer um led piscar, você deve configurar TIMER0 no modo temporizador(bit 5). Atraves da formula dito acima, você calcula o tempo.

    Faz de conta que utilize um cristal de 4Mhz(ciclo maquina = 1us),precaler 1:128, e carregue o TMR0 como o valor 100; O perido será: 1 * 128 * (256 - 100) = 19968us = 20ms. O led piscara num intervalo de 20ms.

    O codigo ficaria assim:
    void main(){
    TMR0 = 100;
    OPTION_REG = 0B10000110;//como os ultimos bits sao 110, prescaler e 1:128.
    TRISB.F0 = 0;

    while(1){
    if(INTCON.TMR0IF==1){//flag de sinalizacao quando TMR0 e maior q 255
    PORTB.F0 = ~PORTB.F0;//pisca o led
    TMR0 = 100;//necessita carregar o TMR0, senao volta pra 0
    INTCON.TMR0IF=0;//limpa a flag
    }
    }
    }

    ResponderExcluir
    Respostas
    1. Nossa, que ágil a resposta hehehe...^^
      Com um exemplo tudo começa ficar mais claro, agora consegui associar a função de cada bit do "OPTION_REG". Li o Cap. 2 e 5 do datasheet mas faltava uma dica para unir a teoria com a pratica.
      A atividade que estou desenvolvendo pede que eu configure a fonte de clock com configuração do pre escaler 1:256 e que siga o seguinte algoritmo:

      configurar fonte de clock
      conf. pre escaler 1:256
      enquanto timer<15625 espere
      timer = 0
      acended lad
      enquando timer<15625, espere
      timer = 0
      apaga led

      O meu código encontra-se assim:

      void main() {

      TRISA=0b11111110; //Porta A têm o pino A0 configurado como "saída"
      OPTION_REG=0b10000111;

      for(;;)
      {
      while (TMR0<255) {
      TMR0=0;
      PORTA=0b00000000;} //Pino A0 libera "saída alta" (5V)
      while (TMR0<255) {
      TMR0=0;
      PORTA=0b00000001;} //Pino A0 libera "saída alta" (5V)
      }

      }

      Mas não funciona por nada hehehe.... alguma luz?

      Excluir
    2. Eu faria assim:
      void main() {
      TRISA = 0b11111110;
      OPTION_REG = 0b10000111;

      for(;;)
      {
      while (TMR0<255);
      TMR0 = 0;
      PORTA = 1;
      while (TMR0<255);
      TMR0 = 0;
      PORTA = 0;

      }
      }

      No seu codigo, dentro do while, vc carregou TMR0=0, como o TMR0=0 sera sempre menor q 255, nunca iria sair do loop.

      Excluir
    3. Entendi, eu havia criado uma função que nunca sairia do loop T_T... Farei apenas mais um questionamento, o que o algoritmo do problema que estou tentando resolver quer dizer com "... timer<15625...", pois, qualquer valor que entro, se maior do que 255, o programa não funciona como esperado.

      Excluir
    4. O módulo timer0 na verdade conta ate 255, pois possui um registro contador(TMR0) de 8 bits. Para o timer1, possui um registro de 16 bits(TMR1H/TMR1L) e pode contar até 65536.

      Excluir
    5. Muito obrigado pelas explicações, apesar de conceitos básicos, foram essenciais para clarear minha vida =)...

      Excluir
  4. Estou com uma duvida
    Estou tentando acender 4 leds um de cada vez com intervalo de 2segundos utilizando o pic 18f4520, porem ele só acende o primeiro?
    Oque estaria errado?


    void main() {
    int segundos = 0;
    trisb=0;
    portb=0;
    T0CON=0b10000110;

    TMR0L=0XEE;
    TMR0H=0X85;
    INTCON.TMR0IF = 0;

    while(1){

    if(segundos == 0 && INTCON.TMR0IF == 1){
    //porta = 0;
    portb.f0 = 1;
    TMR0L=0XEE;
    TMR0H=0X85;
    INTCON.TMR0IF = 0;
    segundos++;

    }else if(segundos == 1 && INTCON.TMR0IF == 1){
    portb.f0 = 0;
    portb.f1 = 1;
    TMR0L=0XEE;
    TMR0H=0X85;
    INTCON.TMR0IF = 0;
    segundos++;

    }else if(segundos == 2 && INTCON.TMR0IF == 1){
    portb = 0;
    portb.f2 = 1;
    TMR0L=0XEE;
    TMR0H=0X85;
    INTCON.TMR0IF = 0;
    segundos++;

    }else if(segundos == 3 && INTCON.TMR0IF == 1){
    portb = 0;
    portb.f3 = 1;
    TMR0L=0XEE;
    TMR0H=0X85;
    INTCON.TMR0IF = 0;
    segundos++;

    }else if(segundos == 4 && INTCON.TMR0IF == 1){
    segundos = 0;
    }else{
    portb = 0;
    TMR0L=0XEE;
    TMR0H=0X85;
    INTCON.TMR0IF = 0;
    segundos++;
    }
    }
    }

    ResponderExcluir
    Respostas
    1. Na linha:
      INTCON.TMR0IF = 0;

      adicione:
      INTCON.TMR0IE = 0;

      Excluir
  5. Olá!
    Veja que no ultimo "else" voce incrementa a variavel segundos. como o intervalo do timer é de 2 segundos(eu acho) durante esse tempo, o pic ira executar esse "else" milhares de vezes, ou seja, a variavel incrementara milhares de vezes, e nunca sera 1,2,3 ou 4.

    simplifiquei seu codigo:

    void main() {
    int segundos = 0;
    trisb=0;
    portb=0;
    T0CON=0b10000110;
    TMR0L=0XEE;
    TMR0H=0X85;
    INTCON.TMR0IF = 0;
    while(1){
    if(INTCON.TMR0IF==1)
    {
    PORTB = (1 << segundos++);
    if(segundos==4) segundos=0;
    TMR0L=0XEE;
    TMR0H=0X85;
    INTCON.TMR0IF = 0;
    }
    }
    }

    ResponderExcluir
  6. Cristiano Jeferson26 de maio de 2013 18:52

    Olá, minha dúvida a seguinte:

    Preciso de uma contagem de 0 a 20ms, ou seja, 0 a 20000us.

    Meu cristal é de 4MHz. Minha aplicação é com USB, então preciso de 48MHz. Consigo isso modificando o prescaler do clock. Mas esse prescaler é o mesmo do timer0?

    Outra coisa, o ciclo de máquina nesse caso seria:
    4/48=0.08333us

    O tempo de overflow é:

    T=ciclo de maq*prescaler*contagem

    20000=0.08333us*128*contagem

    Ta certo isso?

    ResponderExcluir
    Respostas
    1. Olá!
      O prescaler do PLL e do timer0 NAO é o mesmo.
      Vc teria q configurar o prescaler PLL para 1:1 e ativar o PLL.
      Depois vc configura o prescaler do timer0.

      A conta esta certinho!

      Excluir
    2. Cristiano Jeferson26 de maio de 2013 23:15

      Olá Tiago, obrigado pela rápida resposta!

      Existe algum comando no MikroC (sou novato) para que eu possa pegar o valor atual de um timer? Quero dizer, eu quero fazer uma interrupção no timer e pegar o valor da contagem na hora dessa interrupção. No CCS existe o "get_timer0()", existe algo parecido no MikroC?

      Excluir
    3. Recomendo que você leia o datasheet do PIC q vc está utilizando.

      Na verdade não existe nenhum comando, você tem q pegar o valor de registro.
      Provavelmente, vc esta utilizando um timer de 16bits, entao voce tera q pegar o valor do registro TMR0H(8bits) e TMR0L(8bits);
      Exemplo:
      int valorDoTimer; //declara uma varivel do tipo int(16 bits)

      valorDoTimer = (TMR0H<<8) + TMR0L;//desloca 8 bits do TMR0H para esquerda e soma com TMR0L

      Excluir
  7. cara para fazer um programa que tenha um botão com duas funções por exemplo: se eu só o aperto ele faz alguma coisa tipo acende um led mas se eu o aperto e segura por meio segundo ele faz outra coisa. Como eu faço isso?? é com timer??

    ResponderExcluir
    Respostas
    1. Nesse caso, voce pode utilizar delay. Veja um exemplo:

      char funcao = 0;

      void main()
      {

      TRISB = 255;
      TRISC = 0;

      while(1)
      {
      funcao = 0;

      if(PORTB.F0==1)//botao pressionado
      {
      funcao = 1;
      delay_ms(500);

      while(PORTB.F0)// a cada 500ms, uma nova funcao ao botao
      {
      funcao++;
      delay_ms(500);
      }

      switch(funcao)//define uma acao para a funcao
      {
      case 1: PORTC = 1; break;
      case 2: PORTC = 2; break;
      case 3: PORTC = 4; break;
      default: PORTC = 0; break;
      }

      }
      }

      }

      Excluir
    2. vlw cara
      obrigado, me ajudou bastante, gosto muito do seu blog

      Excluir
  8. Olá Boa tarde!
    Encontrei este blog e achei-o muito bom, sendo em C e eu que estou a dar os passos em Mikrobasic.
    Estou a tentar fazer um contador de eventos para contar nº de voltas de uma base de uma paletelizadora e depois desenvolver todo o programa.
    parabéns.
    cump.
    Jorge

    ResponderExcluir
  9. Muito obrigado! Você me ajudou em um antigo problema!

    ResponderExcluir
  10. Primeiro queria dizer que essa página do seu blog é muito legal, li todos os posts e vc explica muito bem.
    Minha duvida com timer é a seguinte.
    Vejo que todo mundo faz um timer que faz alguma coisa alternada, ou seja, com uma base de tempo só. Ex: No seu programa a cada estouro do timer muda o estado de uma saida =~, ou seja, se o timer tiver estouro de 20ms, a cada 20ms a saida estará em nivel 1 e passados 20ms ela vai para nivel 0, assim se visualizarmos essa saida em um osciloscópio teremos um formato de onda quadrada e simétrica. Isso eu consegui, o meu problema é que eu quero uma interrupção assimetrica.

    Por exemplo, quero fazer um programa que fique 2ms em nivel 1 e 18ms em nivel 0, mas queria fazer isso através de uma variável e proporcional, quando um subir o outro desce, assim se o nivel alto se manter por 5ms o baixo se mantém por 15ms.

    Existe uma maneira de fazer isso?

    Outra coisa que percebi é que quando uso timer o delay_ms não funciona.

    ResponderExcluir
  11. Voce pode faz o seguinte:
    Define o estouro do timer para 1ms e...

    char i = 0, state = 0, var = 3;

    //1ms
    void interrupt()
    {
    if (TMR0IF_bit)
    {
    TMR0IF_bit = 0;
    TMR0L = 0x05;
    i++;
    if(i == (2 + var) && state == 0) //Depois de 2ms + var
    {
    PORTB.B0 = 0;
    i = 0;
    state = 1;
    }
    else if(i == (18 - var) && state == 1) //Depois de 18ms + var
    {
    PORTB.B0 = 1;
    i = 0;
    state = 0;
    }


    }
    }

    ResponderExcluir
  12. Obrigado por responder, testei esse código mas não funcionou.
    Você consegue fazer um timer que conte um estou a cada 2us com um oscilador de 8Mhz, no resto eu me viro, a minha maior dificuldade é o timer pois nunca trabalhei com timer antes.

    Obrigado.

    ResponderExcluir
    Respostas
    1. void Interrupt()
      {
      if (TMR0IF_bit)
      {
      TMR0IF_bit = 0;
      TMR0 = 251;
      //Seu código
      }

      void InitTimer0()
      {
      OPTION_REG = 0x88; //Prescaler 1:1
      TMR0 = 251;
      INTCON = 0xA0;
      }

      Excluir
  13. Obrigado mais uma vez por responder, mas está dando erro no TMR0 q eu depois declarei como variavel int, depois fica dando erro no InitTimer0.

    Este código devo colocar acima do void main() ?

    ResponderExcluir
  14. Respostas
    1. void Interrupt()
      {
      if (TMR0IF_bit)
      {
      TMR0IF_bit = 0;
      TMR0L = 0xFB;
      //Seu código
      }
      }

      void InitTimer0()
      {
      T0CON = 0xC8;
      TMR0L = 0xFB;
      GIE_bit = 1;
      TMR0IE_bit = 1;
      }

      void main()
      {
      InitTimer0();

      //Seu código
      }

      Excluir
  15. Opa Tiago, pode me dar uma força?

    Estou usando um Pic 12F675

    O programa que estou tentando criar funciona assim:

    Estou usando GP0 como entrada e GP2 como saida.

    Funciona assim:

    A saida GP2 fica em nivel 1.

    No momento que eu mudo o estado da entrada "GP0" atraves de um botão, depois de 5 minutos a saida vai a 0 e permanece assim por 5s e volta para "1".

    Até ai tudo bem, funciona, porém se eu antes dos 5 minutos deixar de pressionar o botão, não era mais pra acionar a saída, mas não é isso que acontece, mesmo assim a saída vai para "0".

    Pode me ajudar?

    ResponderExcluir
    Respostas
    1. vc tem o programa q vc esta fazendo.
      Eu nao entendi muito, se puder passar mais detalhes.

      Excluir
    2. Bom dia Tiago, obrigado pela atenção.

      Segue o programa.

      void main() {
      ansel = 0;
      cmcon = 7;
      trisio = 0x01;
      gpio = 0;

      while(1){
      if (GP0_bit == 0){
      GP2_bit = 0;
      }
      else{
      delay_ms (300000);
      GP2_bit = 1;
      delay_ms (5000);
      GP2_bit = 0;
      }
      }
      }

      Como sou novo no assunto, ainda não sei trabalhar com os timers e interrupções, meus programas são todos do nível acima, mas tô praticando, e te agradeço por perder tempo comigo. A lógica do programa tá invertida em relação ao que eu escrevi ontem, mas é só isso.

      Excluir
    3. Ah, esqueci,

      O problema que não consigo resolver é: se eu pressiono o botão(GP0_bit) e solto ele não deveria acionar a saída (GP2_bit), mas ele entra no looping de tempo, ai já era. Porque se eu solto o botão, antes dos 5 minutos, ele teria que interromper a contagem do tempo e zerar a contagem.

      Excluir
    4. void main()
      {
      unsigned i=0;
      ansel = 0;
      cmcon = 7;
      trisio = 0x01;
      gpio = 0;

      Label1:
      while(1)
      {
      if (GP0_bit == 0)
      {
      GP2_bit = 0;
      }
      else
      {
      while(GP0_bit && i < 30000)
      {
      delay_ms(10);
      i++;
      }
      if(!GP0_Bit)
      {
      i=0;
      GP2_Bit = 0;
      goto Label1;
      }
      GP2_bit = 1;
      delay_ms(5000);
      GP2_Bit = 0;
      i=0;
      }
      }
      }

      Excluir
    5. Thiago o que significa este Label 1 e o Goto Label?
      Muito obrigado.


































      Excluir
    6. A instruçao goto significa “ir para“. ela direciona o contador de programa do mcu para um endereço, no caso, para o label1, que é o inicio do “while“.

      Excluir
  16. Anderson, você quer que a saida permaneça em nivel 1 durante o tempo que o botão está pressionado ou vc dá um toque no botão e ele fica em nivel 1 por 5s e depois volta pra 0?
    Vi no seu programa que vc colocou um delay de 300.000ms, isso é igual a 300s. Assim qdo entrar no o programa vai manter o ultimo estado, que no caso é 0, por 300 segundos.
    Me diga o que extamente vc quer fazer que acredito que posso te ajudar.
    Se vc quiser mudar o status do que vc está fazendo, antes do tempo que vc está querendo programar, vc não deve usar delay, vc deve usar uma variável que vai contar um numero X e ela será o seu flag, assim vc pode interromper e alterar o status de alguma saída antes do tempo do delay.
    Acontece que o delay em alguns casos não é interessante pois ele trava o programa o resto do código até que o tempo daquela linha onde está o delay estoure.

    Ex.
    while(1){

    PORTB.RB1 = 1; //A saida RB1 irá pra nivel lógico 1
    delay_ms(1000); //RB1 permanecerá assim por 1s até que o microcontrolador leia a próxima linha
    PORTB.RB1 = 0; //Esta linha altera o estado para nivel 0
    delay_ms(20000); //A leitura do código ficará parada aqui até que os 20s desse delay estoure, só depois ele passará pra linha abaixo.
    PORTB.RB2 = 1;
    }

    ResponderExcluir
  17. Na verdade se a entrada for pra 1(botão pressionado), começa a contar 300s pra acionar a saida, porem se eu soltar o botão a saida deveria permanecer no mesmo estado.

    ResponderExcluir
  18. Olá! parabéns pelo tutorial. Só tenho uma dúvida. Se eu quiser usar um tempo de overflow de 1000us e um cristal de 4Mhz, qual o prescaler indicado? Pois estou tentando fazer aqui e sempre dá um tempo enorme de contagem.

    ResponderExcluir
    Respostas
    1. Olá! Obrigado!
      Você pode utilizar um prescaler 1:4 e TMR0 = 6;

      4 / 4MHz = 1us

      1us * 4 * (256 - 6) = 1000us

      Excluir
    2. Obrigado. O problema que estou tendo é que quando mudo o prescaler fica errado. Por exemplo, 4mhz, prescaler 1:8 e overflow de 1000us. 1us*8*(256 - 131) = 1000us com TMR0 = 131, mas quando coloco pra rodar o tempo não bate.

      Excluir
    3. Voce está fazendo assim? Lembre-se de recarregar o TMR0 sempre que houver um overflow. Se o TMR0 for recarregado com 0, não há necessidade de inseri-lo no código.

      void Interrupt()
      {
      //seu código
      TMR0 = 131;
      TMR0IF_Bit = 0;
      }

      void Main()
      {
      OPTION_REG = 0b10000010;
      TMR0 = 131;
      INTCON.GIE = 1;
      INTCON.PEIE = 1;
      INTCON.TMR0IE = 1;

      }

      Excluir
    4. valew Tiago!! Eu estava carregando o tmr0 fora da rotina de interrupção. Agora tá rodando redondo aqui.

      Excluir
  19. Olá Thiago, muito bacana sua explicação sobre o TMR0 mas li as respostas que você deu aos outros colegas e não encontrei uma solução para mim. Estou tentnado implementar um temporizador com o PIC16F628 de pelo menos duas horas, isso acionado por um LDR numa determinada porta. Pois bem, a questão do LDR até posso resolver depois mas já li muitos materiais sobre a manipulação do TMR0 do PIC mas todos acabam falando em acionamento por um segundo de um led, etc. Assim, gostaria de alguma ajuda com esse cálculo para um período maior, caso possa fazê-lo. Obs.: uso CCS e minha pequena base de programação é C ANSI. Grande abraço e tudo de bom. Sandro

    ResponderExcluir
    Respostas
    1. #include <16F628A.h>
      #device adc=8
      #FUSES NOWDT,XT
      #use delay(clock=4000000)

      int32 time=0;
      #int_RTCC
      void RTCC_isr(void) //1000us
      {
      time++;
      if(time == 7200000)
      {
      output_toggle(pin_b0);
      time = 0;
      }
      }

      void main()
      {
      setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);
      setup_timer_1(T1_DISABLED);
      setup_timer_2(T2_DISABLED,0,1);
      enable_interrupts(INT_RTCC);
      enable_interrupts(GLOBAL);
      set_timer0(6);
      set_tris_b(0x00);
      time =0;
      while (TRUE)
      {

      }
      }

      Excluir
    2. Calculo:
      1us * 4 * (256 - 6) = 1000us

      2horas = 120min = 7200 seg == 7200000ms

      Excluir
    3. Salve Tiago!! Estudo completo, hein? (pelo menos com o setor #### eu devia me virar sozinho (rss..).
      Valeu mesmo, seu algoritmo vou guardar prá sempre porque a explicação é perfeita e servirá de base para outros pequenos projetos de final de semana por aqui (ou de um ano inteiro, kkk). Grande abraço e tudo de bom. Sandro.

      Excluir
  20. Tiago, preciso de ajuda com o timer0, mas é para o pic12F675. Preciso fazer um temporizador que fique ligado por 168 horas seguidos, e após este tempo desligar. O programa é inicialmente simples, o problema está na precisão, pois como o tempo é longo, o acumulo de pequenos erros na temporização acaba atrapalhando o resultado final. Você pode me ajudar na questão de precisão desse temporizador ? Agradeço se me der uma ajuda.

    ResponderExcluir
    Respostas
    1. No seu caso poderia utilizar um cristal de 32768Hz.
      Irei fazer um post sobre este assunto!!
      Até mais!!

      Excluir
    2. Valeu Tiago. A resposta veio rápido vai me ajuda muito. Obrigado e parabéns pelo material disponível no blog.

      Excluir
  21. Tiago Você conhece mesmo o pic e o mickroc.
    você poderia me ajudar a sincronizar com a rede eletrica.
    assim um pino fica gerando onda quadrada a 60Hz atraves de um temporizador.
    uma chave fica aberta e conecta um pino contador um sinal externo que varia de 57Hz a 63Hz, quando isso acontece o pino que gera os 60Hz tem que ir de 60Hz suavemente para a frequencia que está entrando nesse pino contador, caso abra a chave o pino que gera o clock deve voltar suavemente para 60Hz, olha já quebrei a cabeça mas é complicado. eu programo com o CCS

    ResponderExcluir
  22. Por favor, preciso fazer um temporizador com o PIC 18F4520, porém não estou conseguindo. Preciso selecionar no display LCD, por meio de um botão, a função TEMPO, que faz a contagem, em segundos, para o acionamento de um motor. Quando a função TEMPO é selecionada será necessário informar o tempo que o motor irá ser acionado. Por exemplo: Preciso que o motor entre em funcionamento após 5 segundos, assim eu selecionaria a função TEMPO no display LCD e incrementaria por meio de um botão, até aparecer o número 5, dessa forma após 5 segundos o motor seria acionado.

    Muito obrigado

    Thiago

    ResponderExcluir
  23. Olá Thiago, gostei muito da sua explicação sobre o TMR0, uso o ccs e estou tentando fazer um temporizador com o PIC16F628a que fique um Led ligado por 6segundos e desligado por 2 horas por uma determinada porta, sempre assim com loop, mas não encontro nada sobre esse tipo de temporizador infinito por horas, apenas segundos preciso de ajuda com esse cálculo para um período maior, pode me ajudar? fico grato por sua ajuda e parabéns pelo blog.

    ResponderExcluir
  24. Olá Thiago,
    Cara, estou com um projeto que que seria mais ou menos assim:
    Tenho um dispositivo que faz um movimento e fica parado "x" segundos (regulado em um temporizador ). Após isso um segundo temporizador faz o mesmo durante "xx" segundos .
    Esses dois movimentos desse dispositivo, gerariam "X" + "XX" segundos , que automaticamente me dariam "Z" quantidades por hora.
    Ex: 1segundo + 2 segundos = 60 minutos / 3 segundos = "Z" quantidades por minuto * 60 minutos= 1200 por hora.
    Não estou conseguindo resolver isso.
    Se por possível me ajudar !!!

    Abraço !

    ResponderExcluir
  25. Olá Thiago,
    Cara, estou com um projeto com PIC 16f877a que seria mais ou menos assim:
    Tenho um dispositivo que faz um movimento e fica parado "x" segundos (regulado em um temporizador ). Após isso um segundo temporizador faz o mesmo durante "xx" segundos .
    Esses dois movimentos desse dispositivo, gerariam "X" + "XX" segundos , que automaticamente me dariam "Z" quantidades por hora.
    Ex: 1segundo + 2 segundos = 60 minutos / 3 segundos = "Z" quantidades por minuto * 60 minutos= 1200 por hora.
    Não estou conseguindo resolver isso.
    Se por possível me ajudar !!!

    Abraço !

    ResponderExcluir
  26. Ola, Thiago
    Estou com um projeto que vai ter varias rotinas no lcd, estou usando um pic 18F452, so que eu acho que ele nao vai suportar a memoria. o que vc me diz uso uma externa ou tem alguma rotina pra minizar a memoria.

    ResponderExcluir
  27. Olá,Thiago.
    Muito boa a sua explicação sobre os timers,mas preciso de sua ajuda.Preciso fazer um contador de pulsos que conte um determinado numero de pulsos que eu determinarei,por exemplo 10 pulso, sendo que isso só pode acontecer depois de acionado um botão,isto feito deverá acionar duas porta: uma com 200 ms e outra acionada direta.

    ResponderExcluir
  28. Como saber o prescaler e como configurar para estourar a cada 1ms

    ResponderExcluir
:) :( ;) :D ;;-) :-/ :X :P :-* =(( :-O X( :7 B-) :-S #:-S 7:) :(( :)) :| /:) =)) O:-) :-B =; I-) L-) :-a :-$ [-( :O) 8-} 2:-P (:| =P~ :-? #-o =D7 :-SS @-) :^o :-w 7:P 2):) :)] :-c ~X( :-h :-t 8-7 X_X :!! \m/ :-q ^#(^ :ar!

Postagens Relacionadas!!