Fork me on GitHub

22/11/13

TUTORIAL: Real Time Clock com PIC

TUTORIAL: Real Time Clock com PIC



Neste post estarei falando sobre como usar o PIC como um relógio de tempo real (RTC).

Trabalhando o Timer1 do PIC com uma fonte de clock externa de 32768Hz você poderá obter tempos bem precisos.

O Timer1 deve ser configurado da seguinte forma:
Bit3: T1OSCEN = 1: Habilita o oscilador do Timer1. ( Pinos T1OSO e T1OSI ).
Bit1: TMR1CS = 1: Fonte de clock externa.

Para fazer um RTC, você precisará de um tempo preciso de 1 segundo. Como o cristal gera 32768 pulsos em 1 segundos, definindo o valor do (TMR1H:TMR1L) para 32768, ele levará exatamente 1 segundo para ocorrer o estouro e a interrupção. ( O Timer1 contará de 32768 até 65536 em 1 segundo e após, ocorrerá o estouro ).



Criei uma biblioteca para facilitar o trabalho com o Timer. Achei interessante também mostrar pra vocês como passar uma função como parâmetro numa função, utilizando o compilador MikroC.

BIBLIOTECA
typedef struct
{
  char sec;
  char min;
  char hrs;
}RTC;

RTC time;

void RTC_Interrupt()
{
  if(TMR1IF_Bit) //Se ocorreu a interrupção
  {
    TMR1IF_Bit = 0; //Limpa a flag de interrupção
    TMR1H = 0x80;
    TMR1L = 0;
    time.sec++;
    if( time.sec == 60 )
    {
        time.sec = 0;
        time.min++;
        if(time.min == 60)
        {
          time.sec = 0;
          time.min = 0;
          time.hrs++;
        }
    }
  }
}

void RTC_Init()
{
     T1CON = 0b00001111; //Prescaler 1:1, Oscilador ligado, Clock Externo
     TMR1H = 0x80;  
     TMR1L = 0;     //Carrega valor de (TMR1H:TMR1L) com 32768
     time.sec = 0;
     time.min = 0;
     time.hrs = 0;
     TMR1IE_Bit = 1; //habilita interrupção do timer1
     PEIE_Bit = 1;  //habilita interrupção dos periféricos
     GIE_Bit = 1;  //Habilita interrupção global
}

//Esta funcao verifica o tempo do RTC com um
// determinado tempo e executa a funcao do parametro
char RTC_Check_Time( char _seg, char _min, char hr, void (*func)() )
{
     if( time.sec == _seg && time.min == _min && time.hrs == hr)
     {
          func();   //Executa a funcao do parametro
          return 1;
     }
     return 0;
}


EXEMPLO: Temporizador
//Copie e cole o código da biblioteca aqui

void LigarLED()
{
     PORTB.B0 = 1;
}

void DesligarLED()
{
     PORTB.B0 = 0;
}

void Interrupt()
{
    RTC_Interrupt();
}

void main()
{
     RTC_Init();
     CMCON = 7;
     TRISB.B0 = 0;
     PORTB.B0 = 0;
     
     while(1)
     {
        //Passados 10 segundos, executa a funcao LigarLED()
        RTC_Check_Time( 10, 0, 0, &LigarLED );  
        
        //Passados 20 segundos, executa a funcao DesligarLED()
        if( RTC_Check_Time(  20, 0, 0, &DesligarLED ) )  
        {
            time.sec = 0;
            time.min = 0;
            time.hrs = 0; //Reinicia o RTC
        }
     }
     
}

10 comentários:

  1. "Show de bola" Tiago. Obrigado pela ajuda. Deus te abençõe !!!

    ResponderExcluir
  2. Tiago, tentei este tutorial em protoboard com o pic 12F675, mas não funcionou. Sabe me dizer como fica os fusíveis e os pinos exatos para ligar o cristal ? Estou tentando, mas sem sucesso.

    ResponderExcluir
    Respostas
    1. O datasheet do PIC12F675 , para configuração do T1CON está me deixando confuso. Se puder, me ajuda com o uso do cristal de 32768hz e o pic12F675, mostrando a configuração dos fuses e como fazer a configuração do oscilador. Muito obrigado.

      Excluir
    2. Você deve ter percebido que os pinos de entrada para o cristal do Timer1 são os mesmo do PIC( pinos 2 e 3 ). Então você deve desativar o cristal do pic alterando o fusivel para INTOSC oscillator: I/O Function on GP4....

      Depois é so configurar o Timer1:
      bit 7-6 = 00;
      bit 5-4 = 00; prescaler 1:1
      bit 3 = 1; habilita o oscilador para timer1
      bit 2 = 1; não sincronizado
      bit 1 = 1; clock externo
      bit 0 = 1; timer1 ligado

      Tambem deverá desativar o comparador e o canal analogico para trabalhar com as outras portas digitais:
      ANSEL = 0;
      CMCON = 7;



      Excluir
    3. Tiago, os ensinamentos acima ate funcionaram, mas ainda me resta duvidas. Veja se pode esclarecer. A fusível INTOSC oscillator: I/O Function on GP4.... ativa o oscilador interno certo? e vendo o datasheet, traduzindo algumas partes encontrei isso:
      "O oscilador Timer1 é compartilhada com o sistema LP
      oscilador . Assim, Timer1 pode usar este modo apenas quando
      o relógio do sistema é derivado do oscilador interno .
      Tal como acontece com o sistema de oscilador LP , o utilizador deve fornecer
      um tempo de atraso de software para assegurar oscilador correcta
      start-up
      Enquanto ativado, TRISIO4 e TRISIO5 estão definidos. GP4
      e GP5 ler '0 ' e TRISIO4 e TRISIO5 são lidos
      '1 ' . "

      Nessa situação, o correto não seria usar o fusível LP ? E se for, como preencher o valor do oscilador pedido pelo mikroC em MHz ?
      Agradeço toda a sua ajuda... Parabéns pelo empenho em ensinar!!!

      Excluir
    4. O problema de ativar o fusivel LP, é que o clock do PIC será de 32768Hz( 0.032768 ), que é muito lento comparado com os 4Mhz interno.

      Excluir
  3. Muito bom! Tiago, teria como fazer utilizando o clock interno do pic? O que eu uso no meu projeto é o PIC18F1220.

    ResponderExcluir
  4. Muito bom Tiago, já vi um Hardware ligando o Cristal 32.768khz exatamente desta forma sempre quis entender como se usava obrigado por compartilhar, muito satisfeito!

    ResponderExcluir
  5. COMO USAR A FUNÇÃO ACIMA PARA FASER UM RELOGIO COM DISPLAY LCD 2X16

    ResponderExcluir
  6. como mostrar horas, minutos e segundos para um relogio? é melhor esse metodo ou ds1307 para o relogio?

    ResponderExcluir

Postagens Relacionadas!!