Fork me on GitHub

23/11/12

Projeto 12: Relógio Digital

Relógio Digital com PIC16F877A Utilizando o Timer0







Esse é um projeto de um relógio digital criado por mim. Utiliza um microcontrolador PIC16F877A e um display LCD 20x2.

A base para a contagem de tempo é o TIMER0, configurado para modo contador com prescaler 1:8, TMR0=5. O clock utilizado é de 8MHz.

Para que a contagem tive-se um intervalo de 1 segundo, foi necessário criar uma variável cnt que incrementava cada estouro do timer e após 1000 estouros (1ms * 1000) fazia que o segundo incrementasse.

Para escrever os dígitos no display de LCD foi necessário pegar cada digito do número e armazená-lo numa variável, para que depois pudéssemos escrevê-lo no LCD.

Nessa nova versão, quando você acerta o relógio, os valores são salvos na memória eeprom, para que quando desligado, depois possa recuperar o tempo salvo.

DOWNLOAD:

CÓDIGO-FONTE:


// LCD module connections
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;
sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD module connections

char seg,m,h,dia;
char *text = "00:00:00";
unsigned cnt;
char flags = 0;

void interrupt()
{
TMR0=5;
cnt++;
INTCON.TMR0IF=0;
if(cnt==1000){
 cnt = 0;
 seg++;
 if(seg==60){
             seg=0;
             m++;
             if(m==60){
                       seg=0;
                       m=0;
                       h++;
                       if(h==24){
                                 seg=0;
                                 m=0;
                                 h=0;
                                 dia++;
                                 if(dia==7){
                                            dia=0;
                                            }
                                 }
                       }
             }
}
}
void main()
{
TRISC = 255;
TRISD = 0;
INTCON.GIE = 1;
INTCON.PEIE = 1;
INTCON.TMR0IE = 1;
OPTION_REG = 0b10000010;
TMR0 = 5;
seg = Eeprom_Read(3);
m = Eeprom_Read(2);
h = Eeprom_Read(1);
dia = Eeprom_Read(0);


Lcd_Init();
Lcd_Cmd(_LCD_CLEAR);
Lcd_Cmd(_LCD_CURSOR_OFF);

while(1)
{

text[6] = seg/10 + '0';
text[7] = seg%10 + '0';
text[3] = m/10 + '0';
text[4] = m%10 + '0';
text[0] = h/10 + '0';
text[1] = h%10 + '0';

Lcd_Out(1, 7, text);

if(PORTC.F0) Flags.B0 = 1;
if(PORTC.F1) Flags.B1 = 1;
if(PORTC.F2) Flags.B2 = 1;
if(PORTC.F3) Flags.B3 = 1;


if(PORTC.F0==0 && Flags.B0)
      {
       Flags.B0 = 0;
       seg++;
       if(seg >= 60) seg=0;
       Eeprom_Write(3, seg);
       }
if(PORTC.F1==0 && Flags.B1)
       {
       Flags.B1 = 0;
       m++;
       if(m >= 60) m=0;
       Eeprom_Write(2, m);
       }
if(PORTC.F2==0 && Flags.B2)
       {
       Flags.B2 = 0;
       h++;
       if(h >= 24) h=0;
       Eeprom_Write(1, h);
       }
if(PORTC.F3==0 && Flags.B3)
       {
       Flags.B3 = 0;
       dia++;
       if(dia >= 7) dia=0;
       Eeprom_Write(0, dia);
       }

switch(dia)
{
case 0:Lcd_Out(2,10,"DOM");break;
case 1:Lcd_Out(2,10,"SEG");break;
case 2:Lcd_Out(2,10,"TER");break;
case 3:Lcd_Out(2,10,"QUA");break;
case 4:Lcd_Out(2,10,"QUI");break;
case 5:Lcd_Out(2,10,"SEX");break;
case 6:Lcd_Out(2,10,"SAB");break;
}

}
}

21 comentários:

  1. qual modo de trocar os dias da semana por outra palavra sem causar "dano" ao tempo, sem dar umas travadinhas no segundo

    ResponderExcluir
    Respostas
    1. é de ir trocando enquanto o programa roda, por exemplo: fica escrito microcontrolados por 1 segundo e em outro fica DOM

      Excluir
    2. vc quer q a cada segundo, alterne a palavra. Se for isto, faz o seguinte, apartir da linha 98 do código:
      if(seg%2==0)//se os segundos for um numero par
      {
      switch(dia){
      case 0:Lcd_Out(2,10,"DOM");break;
      case 1:Lcd_Out(2,10,"SEG");break;
      case 2:Lcd_Out(2,10,"TER");break;
      case 3:Lcd_Out(2,10,"QUA");break;
      case 4:Lcd_Out(2,10,"QUI");break;
      case 5:Lcd_Out(2,10,"SEX");break;
      case 6:Lcd_Out(2,10,"SAB");break;
      }
      }
      else//se for um numero impar
      {
      Lcd_Out(2,5,"Microcontrolandos");
      }

      Excluir
  2. o que eu posso fazer para apagar o que ja tinha sido escrito? nao posso usar o clear pq se nao apaga o relógio tambem, mas se eu tento usar espaços o LCD escreve um monte de coisa e números

    ResponderExcluir
    Respostas
    1. Tá estranho esse negócio aí!!
      Se não utilizar o Clear, o único jeito era mesmo preencher com espaços.

      Excluir
    2. cara eu montei praticamente desse jeito ai só que eu estou utilizando o pic 16f873a, ai se eu uso espaços ele fica doido mas quando eu tiro ele volta ao normal e parece que tem um tanto de espaços sei la parece que se eu coloco poucos espaços ai funciona mas se eu coloco o tanto que precisa para esconder o que a atrás o lcd pifa.

      Excluir
  3. Há um problema no funcionamento do relogio. É que quando acerto o relogio e desligo ele fica desacertado. Como eu faço para superar este problema, utilizando a memoria EEPROM?

    ResponderExcluir
    Respostas
    1. Olá anonimo!!!
      Refiz o projeto, alterei algumas coisas e acrescentei o que você falou. espero que tenha gostado!!

      Abraços,
      Tiago.

      Excluir
  4. Se eu pretender alterar o tipo dos dias, por exemplo: DOM para DOMINGO, e assim sucessivamente, quando pretender acertar, algumas letras se sobrepõem. Gostaria de saber o que devo fazer para que, apenas na linha de baixo do LCD se possa evitar essa sobreposição.
    Aguardo!
    redsoft2008@hotmail.com

    ResponderExcluir
    Respostas
    1. Lcd_Out(2,10,"DOMINGO");
      Lcd_Out(2,10,"SEGUNDA");
      Lcd_Out(2,10,"TERCA ");
      Lcd_Out(2,10,"QUARTA ");
      Lcd_Out(2,10,"QUINTA ");
      Lcd_Out(2,10,"SEXTA ");
      Lcd_Out(2,10,"SABADO ");

      Como a palavra "DOMINGO" possui 7 letras, voce deve completar as outras palavras com "espaços"

      Excluir
    2. na postagem nao aparece muito bem, mas por exemplo, depois da palavra "TERÇA" tem "2 espaços". assim esse dois espaços sobrepoe as duas ultimas letras da palavra "SEGUNDA"

      Excluir
  5. Amigo, montei o relógio igualzinho ao esquema, coloquei um cristal de 8MHz ligado nos pinos 13 e 14, liguei o pino 1 em VPP, quando gravei o programa o mesmo não funcionou, sendo que testei no proteus e funcionou, poderia me ajudar?
    Desde ja agradeço.

    ResponderExcluir
  6. Esqueci de mencionar que não conheço muito sobre a programação em C, estou aprendendo a programar em assembly para 8051.

    ResponderExcluir
  7. ola gostaria que vc colocasse esse relogio mas usando o pic16F628a
    ou mandasse para min
    obrigado estou gostando muito do site

    ResponderExcluir
  8. Poderia usar o PIC 16F628A? A linguagem é assembly?

    ResponderExcluir
    Respostas
    1. A linguagem utilizada é C. Pode utilizar sim o PIC16F628A. Abraços.

      Excluir
  9. Olá, adicionei algumas coisas no seu projeto, como dois despertadores para tocar em horas cheias acionando saídas para controlar motors. Posso postá-lo aqui posteriormente se interessarem. Mas minha dúvida é quanto ao horário seguir contando caso seja desligada a alimentação, é possível nesse tipo de relógio? Ou teria que ser com um relógio de precisão externo com comunicação I2C? Abraço.

    ResponderExcluir
    Respostas
    1. Bom dia Lucas, gostei do seu projeto. Posso ter acesso a ele? email: valdineisalvador@gmail.com

      Excluir
  10. Olá, quero adicionar um alarme despertador neste projeto colocando no pino RC7 um Buzzer com um BC548. Como fica o código?

    ResponderExcluir

Postagens Relacionadas!!