Ir ao conteúdo
  • Cadastre-se
DELPITEC

Contar segundos com PIC + LCD

Recommended Posts

Boa noite!
 
Estou tentando fazer um programa simples com o PIC 18F2550 em C.
O programa consiste em, apenas, colocar o valor de um contador de h/seg/min em um display LCD.
 
O grande problema é que, na simulação do proteus, com o passar do tempo, os segundos ficam atrasados em relação ao "tempo real".
 
A única maneira foi compensar esse atraso com o dalay do loop em 995ms (ao invés de 1000ms).
 
Foto do hardware no proteus em anexo
 
O programa segue abaixo. Se alguém conseguir me ajudar fico muito grato.
 
 
-----------------------------------------------------------------------------------------------------------------------------------------------
 
 
#include <18F2550.h>
 
 
#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH , > 10 mhz for PCD)
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES BORV20                   //Brownout reset at 2.0V
#FUSES PUT                      //Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES PBADEN                   //PORTB pins are configured as analog input channels on RESET
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES MCLR                     //Master Clear pin enabled
#FUSES LPT1OSC                  //Timer1 configured for low-power operation
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PLL1                     //No PLL PreScaler
#FUSES CPUDIV4                  //System Clock by 4
#FUSES USBDIV                   //USB clock source comes from PLL divide by 2
#FUSES VREGEN                   //USB voltage regulator enabled
 
#use delay(clock=20000000)
 
 
//===================================== FUSES ===================================
 
 
#define LCD_DATA_PORT getenv("SFR:PORTb")
#define LCD_ENABLE_PIN  PIN_b2
#define LCD_RS_PIN      PIN_b0
#define LCD_RW_PIN      PIN_b1
#define LCD_DATA4       PIN_b4
#define LCD_DATA5       PIN_b5
#define LCD_DATA6       PIN_b6
#define LCD_DATA7       PIN_b7
 
#include "lcd2.c"
 
int ihoras, iminutos, isegundos;
 
 
void main()
{
 
//==========================================
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF);
   setup_spi(SPI_SS_DISABLED);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
//==========================================
 
ihoras = iminutos = isegundos = 0;
lcd_init();
 
while (true)
{  
printf (lcd_putc, "\fRelogio DigiPIC\n%dh %dmin %ds"ihoras, iminutos, isegundos);
delay_ms(995);
isegundos++;
 
if (isegundos == 60)
   {
   iminutos++;
   isegundos = 0;
   }
if (iminutos == 60)
   {
   ihoras++;
   iminutos = 0;
   }
if (ihoras == 24)
   ihoras = iminutos = isegundos = 0; 
}
 
}
 
 

 

post-759553-0-60604400-1426984756_thumb.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Amigo isso é normal quando se usa só sw. A explicação é que o mc leva um tempinho a+ pra entrar, sair da rotina, escrever no display, fazer continhas e etc. E qualquer outra função que você colocar no loop vai zoar ainda mais. Tente algo com o hw como p.ex. interrupção por timer e incremente uma variável "segundo" dentro dela. No loop faça algo assim

 

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

 

Há também a opção de colocar um rtc externo mas acho que não é seu momento

Sorry, ccs&eu=não róla

abç

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá Isadora.

 

Era exatamente o problema que eu estava imaginando que estava acontecendo.

Não sei usar ainda as interrupções direito. 

 

Vou aproveitar que você veio me dar um help:

 

-O que seria hw? (haha)

-E no comando minuto=segundo%60; está atribuindo a variável minuto o resultado inteiro de segundo dividido por 60? Daí coloco isso no loop do while (true), certo? 

 

É que eu comecei a programar em C na faculdade, daí não precisamos nos preocupar tanto com esses problemas de tempo porque a gente apenas fazia programas pra pegar caracteres do teclado, brincar com ponto flutuante, funções...agora que estou entrando no mundo dos uC.

 

Obrigadoo pela atenção, já ajudou muito, pelo menos meu clock deve estar configurado certo haha.

Compartilhar este post


Link para o post
Compartilhar em outros sites

sw=software (ou moleza)

hw=hardware (ou dureza, num e mole não). No caso dos mc (microcontroladores) são os circuitos internos auxiliares, timers, interfaces e tal

Interrupção é algo que facilita sua vida. Quase como um co-processador sem sê-lo. O mc está num loop infinito e é interrompido por algum evento pra tratar de outros assuntos. Depois volta exatamente onde estava. Chovi no molhado? No seu caso, imagine-o sendo interrompido exatamente a cada segundo e incrementando uma variável com nome sujestivo "segundo"

Acho que errei... ninguém é perfeito. O correto é minuto=segundo/60 e hora=minuto/60. Tem um lance de usar a operação de resto % mas agora num to conseguindo pensar direito (se é que algum dia consegui). Outra hora dou uma analisada melhor...

abç

Compartilhar este post


Link para o post
Compartilhar em outros sites

Que maravilha de posts Isa! 

Espero um dia ter esse conhecimento para conseguir ajudar as pessoas.

 

Vamos por partes...

 

Não queria corrigir sem ter certeza, mas % é quando tu faz uma divisão e pega o resto.

No caso se dividir dois números e armazenar o resultado (quebrado) em uma variável inteira ele armazena só o número inteiro.

 

ex:

int a

a = 3/2

(a = 1)

 

E quanto a interrupção, até que consigo ver sentido.

A única preocupação do loop da interrupção seria incrementar uma variável segundo, o que não exigiria tanto tempo, e o resto deixaria por conta do programa em si (corrija-me se eu estiver errado).

 

Fico muito agradecido pela ajuda, vou tentar implementar o código e postar aqui para o pessoal que tiver a mesma dúvida que a minha consiga resolver!

 

Tudo de bom

Compartilhar este post


Link para o post
Compartilhar em outros sites

1ª mente agradeço pelas raras gentis palavras

Elocubremos...

até 1hora 3600 segundos isso dá certo

minuto=seg/60;segundo=seg%60;

É que já usei isso prum timer e daí a confusão

pra 24h 86400 segundos, a mágica é outra. 1ªmente 'seg' vai ter que ser mais que int (maior que 16bits 65535,0xffff) tipo double seg;
você ate poderia bolar uma operação de resto com isso mas acho que variaveis 32 bits forçam a cabecinha de um mc 8 bits (e muito mais a minha kk)
O mais otimizado seriam as 3 de 8 bits como você está fazendo mesmo

unsigned char isegundos,iminutos,ihoras;//variáveis globais

e manipulá-las numa interrupção de 1Hz

isegundos++;if (isegundos == 60) //ao invés disso, faça if (isegundos>59)   {   iminutos++;   isegundos = 0;   }if (iminutos == 60) //ao invés disso, faça if (iminutos>59)   {   ihoras++;   iminutos = 0;   }if (ihoras == 24) //ao invés disso, faça if (horas>23)   ihoras = iminutos = isegundos = 0;

Além é claro de facilitar na hora do acerto do relógio. E a operação acima não demanda tanto tempo conforme teu temor. De fato pode até ser + rápida do que uma simples operação com double p.ex.

E porquê usar '>' ao invés de '=='? você pode não acreditar mas aqui no mundo real, variáveis (principalmente os temidos vetores) têm vida própria. Digamos que isegundos resolva 'assumir' o valor 61, ou ihoras 35?. Sinistro...
Cara... talvez não tenha nada a ver. Só doidêra mesmo kk.

Portanto dominar interrupts do timer: seu próximo passo evolutivo. Sorry again pelo !ccs
Sucessos!

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Claro. Para as 24 horas os 16 bits da variável int não são o suficiente para fazer a divisão.

 

Tu sugere que eu coloque aqueles IFs dentro do loop da interupção ?

 

Essa semana tentarei aprender a maldita interrupção e utilizar neste programinha que estou tentando fazer.

 

Mas acho que entendi, o melhor a se fazer é colocar a menor quantidade de coisas dentro do loop de contagem quando se depende de tempo. Até porque parando para olhar, dentro do loop de contagem do meu programa (que é o próprio while) além dos IFs existe uma biblioteca inteira de LCD sendo executada. Deve ficar pesado mesmo.

 

 

Enfim,vou tentar dar uma separada nessas funções aqui e volto com uma resposta.

 

Obrigado de novo!!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Gênio!

 

Sim dentro da interrupt.

 

você é mais que isso. deve aprender em menos de uma semana.

 

Isso não vai fazer sentido pois não vai mais depender de tempo. O relógio vai rolar sozinho na interrupt, lembra? você pode (e deve) fazer o tudo que quiser dentro do loop desde que respeite as conexões com a interrupt

 

É isso: separe mas conecte.

 

E porque separado se escreve tudo junto e tudo junto se escreve separado? eu hein... e nem bebi.. ainda.

 

abç de novo

Compartilhar este post


Link para o post
Compartilhar em outros sites

 você pode (e deve) fazer o tudo que quiser dentro do loop desde que respeite as conexões com a interrupt

 

Era isso que eu estava tentando dizer no meu post anterior hehe

 

No caso, a interrupt só se encarrega de incrementar a variável segundo e o resto deixo por conta do programa fora da interupt 

(creio que seja isso)

 

Mas valeu mesmo pela ajuda, muito bom falar com alguém sobre essas dúvidas.

 

Fico 24h por dia pensando nesse maldito programa mas meus compromissos não deixam eu parar para brincar um pouco. 

 

Se tudo der certo,hoje de madrugada consigo dar uma futricada hahahahaha

 

Sem palavras para agradecer Isa.

 

Quero fazer para depois deixar registrado aqui caso alguém tenha o mesmo problema que o meu 

 

Abraçoo

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bom, quanto menos coisas na interrupt, melhor. E mais melhor de bão ainda se tiver várias interrupções diferentes. No entanto sugiro se preocupar com isso numa etapa mais avançada. No seu caso sugiro que deixe o trabalho sujo abaixo para a interrupt mesmo:

if (tempo_on) isegundos++;if (isegundos>59)   {   iminutos++;   isegundos = 0;   }if (iminutos>59)   {   ihoras++;   iminutos = 0;   }if (ihoras>23)   ihoras = iminutos = isegundos = 0;

Vai facilitar sua vida - dados mastigados - e não deve atrapalhar noutras atividades. Uma evoluidinha dum post pro outro é o tempo_on = para/continua tempo. Queria que fosse simples assim no mundo real no fds (fim de semana!)

tempo_on=0;// kk

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá!!

 

Depois de muito tentar, consegui utilizar as interupções e consegui fazer um relógio digital com PIC.

Como era só para aprender, acabei utilizando o oscilador RC interno do pic a 8MHz.

 

Deixo o código que fiz em anexo (perdoem a "firula" no título, mas a alegria foi demais haha).

Acabei fazendo um relógio com despertador e com display 7 segmentos multiplexados (fiz para aprender o funcionamento). 

Enfim, ele está todo comentado.

 

Obrigado a todos que ajudaram!

 

Pode encerrar o tópico!

 

relogiodigital.txt

post-759553-0-69685100-1430279560_thumb.

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora





Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações 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

×