Ir ao conteúdo
  • Comunicados

    • Gabriel Torres

      Seja um moderador do Clube do Hardware!   12-02-2016

      Prezados membros do Clube do Hardware, Está aberto o processo de seleção de novos moderadores para diversos setores ou áreas do Clube do Hardware. Os requisitos são:   Pelo menos 500 posts e um ano de cadastro; Boa frequência de participação; Ser respeitoso, cordial e educado com os demais membros; Ter bom nível de português; Ter razoável conhecimento da área em que pretende atuar; Saber trabalhar em equipe (com os moderadores, coordenadores e administradores).   Os interessados deverão enviar uma mensagem privada para o usuário @Equipe Clube do Hardware com o título "Candidato a moderador". A mensagem deverá conter respostas às perguntas abaixo:   Qual o seu nome completo? Qual sua data de nascimento? Qual sua formação/profissão? Já atuou como moderador em algo outro fórum, se sim, qual? De forma sucinta, explique o porquê de querer ser moderador do fórum e conte-nos um pouco sobre você.   OBS: Não se trata de função remunerada. Todos que fazem parte do staff são voluntários.
Entre para seguir isso  
magnoedu

Migrando relógio do 16F877A para o 16F628A

Recommended Posts

Ola amigos estou tentando migrar o grande projeto do amigo Matheus para 16f628a o projeto original do amigo e para o 16f877a simulei no proteus e funcionou mas queria migrar para 16f628a por que e o que eu tenho na minha regiao.

o amigo Matheus vai nos ajudar assim compartilhamos informações.

acredito que meu problema e no driver do lcd 4 bits estou usando uma versao modificado do senhor Fabio.

estou usando a mesma configuração de hardware do Josepino.


Programa teste para fazer um relógio com o 16F877A
Implementada funções que mostram data e dia da semana
Teste promo_version v1.1
by MatheusLPS (Koala)
=============================================================================*/

#include <16F628A.h> //O PIC utilizado, obrigatório!
#FUSES NOWDT //Sem Watch dog, evitando reset
#FUSES XT //Crystal de oscilação igual a 4mhz
#FUSES PUT //Tempo de início do PIC
#FUSES NOPROTECT //Codigo sem proteção de leitura, software livre!
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection


#use delay(clock=4000000) // Definição do clock utilizado. Obrigatório!

#include <lcd4b.C> //Inclusão da biblioteca de LCD. Obrigatório!

// D0 enable //Pinos utilizados pelo LCD. Podem ser alterados.
// D1 rs
// D2 rw
// D4 D4
// D5 D5
// D6 D6
// D7 D7

/*=====================
Meu Botões:
=======================*/

#define BOTAO1 PIN_B0 //Botão de escolha de ajuste das funções.
#define BOTAO_INCREMENTO PIN_B1 //Botão incremento de variáveis.
#define BOTAO_DECREMENTO PIN_B2 //Botão de decremento das variáveis.
//Foram utilizados resistores pull-up e
//pull-down em todos os botões para
//evitar ruídos.

/*=====================
Minhas variáveis:
=======================*/

int16 q=0; //Variável que incrementa a cada 0.5s dentro da interupção do timer1.
int s=0; //Variável dos segundos, incrementa na metade de q.
int m=0; //Variável dos minutos. 0 a 59
int h=0; //Variável das horas. 0 a 23.
int contador=0; //Variável de controle do botão de ajuste.
int ndia_semana=1; //Variável dos dias da semana, é associada a uma string.
int dia=1; //Variável dos dias do mês. 0 a 31.
int mes=1; //Variável dos meses. 0 a 12.
int16 ano=2010; //Variável dos anos. 2000 a 2099.

/*=====================
Minha Interrupção:
=======================*/

#int_TIMER1 //Interrupção do Timer1
void temp1s(void) //Funcão. O que deverá ser feiro a cada interrupão.
{
q++; //Variável q incrementada a cada estouro do Timer1
set_timer1 (3036); //Preload do Timer1
}

/*=====================
O programa Principal:
=======================*/
void main()
{
lcd_init(); //Inicializa o LCD (obrigatório)!

lcd_gotoxy (2,1); //Coluna 6, linha 1.
lcd_putc("Projeto Tempo:");
delay_ms(2000);
lcd_gotoxy (2,2);
lcd_putc("Com PIC16F877A");
delay_ms(2000);
lcd_putc ("\f");
lcd_gotoxy (2,1);
lcd_putc("Promo Version");
delay_ms(2000);
lcd_gotoxy (6,2);
lcd_putc ("1.10");
delay_ms(2000);
lcd_putc ("\f");
lcd_gotoxy (7,1);
lcd_putc("by");
lcd_gotoxy (2,2);
lcd_putc ("Matheus Koala");
delay_ms(3000);
lcd_putc ("\f");
delay_ms(1000);
lcd_gotoxy (1,1);
lcd_putc ("Iniciando");
lcd_gotoxy (10,1);
lcd_putc (".");
delay_ms(500);
lcd_gotoxy (11,1);
lcd_putc (".");
delay_ms(500);
lcd_gotoxy (12,1);
lcd_putc (".");
delay_ms(500);
lcd_gotoxy (13,1);
lcd_putc (".");
delay_ms(500);
lcd_gotoxy (14,1);
lcd_putc (".");
delay_ms(500);
lcd_gotoxy (15,1);
lcd_putc (".");
delay_ms(500);
lcd_gotoxy (16,1);
lcd_putc (".");
delay_ms(500);
lcd_putc ("\f");
delay_ms(1000);

setup_timer_1 (T1_INTERNAL | T1_DIV_BY_8); //Configuração do Timer1 para clock interno = 1E6 dividido por 8
set_timer1 (3036); //Preload do Timer1
enable_interrupts(INT_TIMER1); //Habilita interrupção timer1
enable_interrupts(global); //habilita interrupcão global

while(TRUE) //Loop Principal
{
/*=====================================================================
Teste do botão de ajuste. A medida que é precionado, a variável contador
incrementa e as diversas funções de ajustes podem ser efetuadas. São 6
funções de ajuste, HORA, MINUTO, DIA DA SEMANA,DIA DO MES, MÊS e ANO. A
cada ajuste de uma função, o menu principal com todas as informações é
mostrado.
=====================================================================*/

if (input(BOTAO1)) //Teste do botão.
{
delay_ms (100); //Para evitar retorno.
if (contador>11) //Se maior q 11, zera o contador.
{
contador=0;
}

contador++; //Incremento da variável contador.
}

switch (contador) //Depois de incrementada, a variável CONTADOR
{ //assume um dos casos a seguir:
case 1: //Menu de ajuste da HORA.
{
if (input (BOTAO_INCREMENTO)) //Incrementa a variável H(hora).
{
delay_ms (75);
h++;

if (h>23) //Se a hora for maior que 23, reset.
{
h=0;
}
}

if (input (BOTAO_DECREMENTO)) //Decrementa a variável H(hora).
{
delay_ms (75);
h--;

if (h==255) //H é uma variável inteira de 8 bits.
{ //Quando é decrementada para um valor
h=23; //menor que zero, se torna 255. Ou seja,
} //deve voltar para 23.
}

q=0; //Quando se está em algum menu, Q é resetada.
lcd_gotoxy (1,1); //Vá para a coluna 1 e linha 1 do LCD.
printf (lcd_putc, "\fAjuste Hora:%02u", h); //Escreva com 2 digitos a variável H.
delay_ms (100); //Mantenha na tela.
break;
}

case 3: //Menu de ajuste do MINUTO. Idem ao anterior.
{
if (input (BOTAO_INCREMENTO))
{
delay_ms (75);
m++;

if (m>59) //Diferente aqui.
{
m=0;
}
}

if (input (BOTAO_DECREMENTO))
{
delay_ms (75);
m--;

if (m==255) //Igual aqui.
{
m=59;
}
}

q=0;
lcd_gotoxy (1,1);
printf (lcd_putc, "\fAjuste Minuto:%02u", m);
delay_ms (100);
break;
}

case 5: //Menu de ajuste do DIA DA SEMANA.
{
/*=====================================================================
Ajuste do DIA DA SEMANA. A função ficou meio bagunçada. Pesquisarei
um pouco sobre como trasformar uma string numa variável. Só
consegui fazer isso com 1 (um) caracter, mas não é o ideal. Depois disso,
provavelmente essa parte ficará mais enxuta.

A função ficou assim: Uma variável chamada ndia_semana(número dia da
semana) é incrementada de 1 a 7. Cada número é associado a um dia da
semana. 1 é Domingo, 2 é Segunda e assim por diante. Se ndia_semana for
maior que 7, ela é resetada em 1 de novo. Utilizei a função SWITCH para
associar cada número de 1 a 7 a cada dia da semana.
=====================================================================*/
if (input (BOTAO_INCREMENTO))
{
delay_ms (100);
ndia_semana++;
if (ndia_semana>7)
{
ndia_semana=1;
}

}

if (input (BOTAO_DECREMENTO))
{
delay_ms (75);
ndia_semana--;
if (ndia_semana==255)
{
ndia_semana=7;
}
}

switch (ndia_semana)
{
case 1:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "\fDia da Semana:\nDomingo ");
delay_ms (100);
break;
}

case 2:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "\fDia da Semana:\nSegunda ");
delay_ms (100);
break;
}

case 3:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "\fDia da Semana:\nTerca ");
delay_ms (100);
break;
}

case 4:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "\fDia da Semana:\nQuarta ");
delay_ms (100);
break;
}

case 5:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "\fDia da Semana:\nQuinta ");
delay_ms (100);
break;
}

case 6:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "\fDia da Semana:\nSexta ");
delay_ms (100);
break;
}

case 7:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "\fDia da Semana:\nSabado ");
delay_ms (100);
break;
}
}

q=0; //Variável q sempre resetada nos menus.
break;
}

case 7: //Menu de ajuste do DIA DO MES. Idem ao caso 3.
{
if (input (BOTAO_INCREMENTO))
{
delay_ms (100);
dia++;
if (dia>31)
{
dia=1;
}

}

if (input (BOTAO_DECREMENTO))
{
delay_ms (75);
dia--;
if (dia==0)
{
dia=31;
}
}

q=0;
lcd_gotoxy (1,1);
printf (lcd_putc, "\fAjuste dia Mes: \n%02u", dia);
delay_ms (100);
break;
}

case 9: //Menu de ajuste do MES. Idem ao caso 3.
{
if (input (BOTAO_INCREMENTO))
{
delay_ms (100);
mes++;
if (mes>12)
{
mes=1;
}

}

if (input (BOTAO_DECREMENTO))
{
delay_ms (75);
mes--;
if (mes==0)
{
mes=12;
}
}

q=0;
lcd_gotoxy (1,1);
printf (lcd_putc, "\fAjuste Mes: \n%02u", mes);
delay_ms (100);
break;
}

case 11: //Menu de ajuste do ANO. Idem ao caso 3.
{
if (input (BOTAO_INCREMENTO))
{
delay_ms (100);
ano++;
if (ano>2099)
{
ano=2000;
}

}

if (input (BOTAO_DECREMENTO))
{
delay_ms (75);
ano--;
if (ano==1999)
{
ano=2099;
}
}

q=0;
lcd_gotoxy (1,1);
printf (lcd_putc, "\fAjuste Ano: \n%Lu", ano);
delay_ms (100);
break;
}

default: //Menu principal. Mostra todas as informações.
{
s=q/2; //A variável Q incrementa a 2Hz, então os segundos
//devem ser a metade.
if (s==60) //Se for igual a 60, reset em Q e S. M incrementa.
{
q=0;
s=0;
m++;
}

if (m>59)
{
m=0;
h++;
}

if (h>23) //Se H(horas) for maior q 23, reset. DIA DA SEMANA
{ //e DIA DO MÊS incrementam.
dia++;
ndia_semana++;
h=0;
}

if (ndia_semana>7)
{
ndia_semana=1;
}

switch (ndia_semana) //Os DIAS DA SEMANA só alteram sozinhos no menu
{ //principal. Idem ao caso 5.
case 1:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "DOMINGO ");
delay_ms (100);
break;
}

case 2:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "SEGUNDA ");
delay_ms (100);
break;
}

case 3:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "TERCA ");
delay_ms (100);
break;
}

case 4:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "QUARTA ");
delay_ms (100);
break;
}

case 5:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "QUINTA ");
delay_ms (100);
break;
}

case 6:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "SEXTA ");
delay_ms (100);
break;
}

case 7:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "sábado ");
delay_ms (100);
break;
}
}

switch (mes) //Para saber se um mês possui 31, 30 ou 28 dias.
{ //Numa versão mais nova, farei essa rotina mais enxuta.
case (1):
{
if (dia>31)
{
dia=1;
mes++;
}
break;
}

case 2:
{
if (dia>28)
{
dia=1;
mes++;
}
break;
}

case (3):
{
if (dia>31)
{
dia=1;
mes++;
}
break;
}

case (4):
{
if (dia>30)
{
dia=1;
mes++;
}
break;
}

case (5):
{
if (dia>31)
{
dia=1;
mes++;
}
break;
}

case (6):
{
if (dia>30)
{
dia=1;
mes++;
}
break;
}

case (7):
{
if (dia>31)
{
dia=1;
mes++;
}
break;
}

case (8):
{
if (dia>31)
{
dia=1;
mes++;
}
break;
}

case (9):
{
if (dia>30)
{
dia=1;
mes++;
}
break;
}

case (10):
{
if (dia>31)
{
dia=1;
mes++;
}
break;
}

case (11):
{
if (dia>30)
{
dia=1;
mes++;
}
break;
}

case (12):
{
if (dia>31)
{
dia=1;
mes=1;
ano++;
}
break;
}
}

lcd_gotoxy (9,1);
printf (lcd_putc, "%02u:%02u:%02u\n%02u/%02u/%Lu Koala", h, m, s, dia, mes, ano);
delay_ms (100);
break;
}
}
}
}
/*=============================================================================

driver lcd


/* MOD_LCD.C - Biblioteca de manipulação de módulo LCD */
/* */
/* Autor: Fábio Pereira */
/* */
/************************************************************************/

// As definições a seguir são utilizadas para acesso aos pinos do display
// caso o pino RW não seja utilizado, comente a definição lcd_rw
#ifndef lcd_enable
#define lcd_enable pin_a2 // pino enable do LCD
#define lcd_rs pin_a0 // pino rs do LCD
//#define lcd_rw pin_e2 // pino rw do LCD
#define lcd_b4 pin_b4 // pino de dados d4 do LCD
#define lcd_b5 pin_b5 // pino de dados d5 do LCD
#define lcd_b6 pin_b6 // pino de dados d6 do LCD
#define lcd_b7 pin_b7 // pino de dados d7 do LCD
#endif

#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 linhas
#define lcd_seg_lin 0x40 // Endereço da segunda linha na RAM do LCD

// a constante abaixo define a seqüência de inicialização do módulo LCD
byte CONST INI_LCD[4] = {0x20 | (lcd_type << 2), 0xf, 1, 6};

byte lcd_le_byte()
// lê um byte do LCD (somente com pino RW)
{
byte dado;
// configura os pinos de dados como entradas
input(lcd_b4);
input(lcd_b5);
input(lcd_b6);
input(lcd_b7);
// se o pino rw for utilizado, coloca em 1
#ifdef lcd_rw
output_high(lcd_rw);
#endif
output_high(lcd_enable); // habilita display
dado = 0; // zera a variável de leitura
// lê os quatro bits mais significativos
if (input(lcd_b7)) bit_set(dado,7);
if (input(lcd_b6)) bit_set(dado,6);
if (input(lcd_b5)) bit_set(dado,5);
if (input(lcd_b4)) bit_set(dado,4);
// dá um pulso na linha enable
output_low(lcd_enable);
output_high(lcd_enable);
// lê os quatro bits menos significativos
if (input(lcd_b7)) bit_set(dado,3);
if (input(lcd_b6)) bit_set(dado,2);
if (input(lcd_b5)) bit_set(dado,1);
if (input(lcd_b4)) bit_set(dado,0);
output_low(lcd_enable); // desabilita o display
return dado; // retorna o byte lido
}

void lcd_envia_nibble( byte dado )
// envia um dado de quatro bits para o display
{
// coloca os quatro bits nas saidas
output_bit(lcd_b4,bit_test(dado,0));
output_bit(lcd_b5,bit_test(dado,1));
output_bit(lcd_b6,bit_test(dado,2));
output_bit(lcd_b7,bit_test(dado,3));
// dá um pulso na linha enable
output_high(lcd_enable);
output_low(lcd_enable);
}


void lcd_envia_byte( boolean endereco, byte dado )
{
// coloca a linha rs em 0
output_low(lcd_rs);
// aguarda o display ficar desocupado
//while ( bit_test(lcd_le_byte(),7) ) ;
// configura a linha rs dependendo do modo selecionado
output_bit(lcd_rs,endereco);
delay_us(100); // aguarda 100 us
// caso a linha rw esteja definida, coloca em 0
#ifdef lcd_rw
output_low(lcd_rw);
#endif
// desativa linha enable
output_low(lcd_enable);
// envia a primeira parte do byte
lcd_envia_nibble(dado >> 4);
// envia a segunda parte do byte
lcd_envia_nibble(dado & 0x0f);
}


void lcd_ini()
// rotina de inicialização do display
{
byte conta;
output_low(lcd_b4);
output_low(lcd_b5);
output_low(lcd_b6);
output_low(lcd_b7);
output_low(lcd_rs);
#ifdef lcd_rw
output_high(lcd_rw);
#endif
output_low(lcd_enable);
delay_ms(15);
// envia uma seqüência de 3 vezes 0x03
// e depois 0x02 para configurar o módulo
// para modo de 4 bits
for(conta=1;conta<=3;++conta)
{
lcd_envia_nibble(3);
delay_ms(5);
}
lcd_envia_nibble(2);
// envia string de inicialização do display
for(conta=0;conta<=3;++conta) lcd_envia_byte(0,INI_LCD[conta]);
}

void lcd_pos_xy( byte x, byte y)
{
byte endereco;
if(y!=1)
endereco = lcd_seg_lin;
else
endereco = 0;
endereco += x-1;
lcd_envia_byte(0,0x80|endereco);
}

void lcd_escreve( char c)
// envia caractere para o display
{
switch (c)
{
case '\f' : lcd_envia_byte(0,1);
delay_ms(2);
break;
case '\n' :
case '\r' : lcd_pos_xy(1,2);
break;
case '\b' : lcd_envia_byte(0,0x10);
break;
default : lcd_envia_byte(1,c);
break;
}
}

char lcd_le( byte x, byte y)
// le caractere do display
{
char valor;
// seleciona a posição do caractere
lcd_pos_xy(x,y);
// ativa rs
output_high(lcd_rs);
// lê o caractere
valor = lcd_le_byte();
// desativa rs
output_low(lcd_rs);
// retorna o valor do caractere
return valor;
}
/************************************************************************/

post-566156-13884957120479_thumb.jpg

Editado por Bcpetronzio
Inserir Spoiler

Compartilhar este post


Link para o post
Compartilhar em outros sites

Opa, tá na mão colega.... Ahh e não é grande projeto.... é apenas um teste. O programa está imenso e não coube todo no 16F628A, então tive que retirar as mensagens de boas vindas. Quando tiver mais tempo, provavelmente modificarei para enxugá-lo.

De toda forma, já fiz a modificação que você pediu, passei do 16F877A para o 16F628A.

Tive que adicionar uma outra biblioteca de LCD. Com essa nova biblioteca, você consegue facilmente mudar os pinos de acordo com sua necessidade.

Circuito com 16F877A:

semttulouw.jpg

Circuito com 16F628A:

circuitos.jpg

LCD_flex dirver:

http://www.ccsinfo.com/forum/viewtopic.php?t=24661

LCD_driver Modificado por mim para funcionar no 16F628A:



// These pins are for the Microchip PicDem2-Plus board,
// which is what I used to test the driver. Change these
// pins to fit your own board.

#define LCD_DB4 PIN_B4
#define LCD_DB5 PIN_B5
#define LCD_DB6 PIN_B6
#define LCD_DB7 PIN_B7

#define LCD_E PIN_B0
#define LCD_RS PIN_B1
#define LCD_RW PIN_B2

// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.

//#define USE_LCD_RW 1

//========================================

#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line


int8 const LCD_INIT_STRING[4] =
{
0x20 | (lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8 dots
0xc, // Display on
1, // Clear display
6 // Increment cursor
};


//-------------------------------------
void lcd_send_nibble(int8 nibble)
{
// Note: !! converts an integer expression
// to a boolean (1 or 0).
output_bit(LCD_DB4, !!(nibble & 1));
output_bit(LCD_DB5, !!(nibble & 2));
output_bit(LCD_DB6, !!(nibble & 4));
output_bit(LCD_DB7, !!(nibble & 8));

delay_cycles(1);
output_high(LCD_E);
delay_us(2);
output_low(LCD_E);
}

//-----------------------------------
// This sub-routine is only called by lcd_read_byte().
// It's not a stand-alone routine. For example, the
// R/W signal is set high by lcd_read_byte() before
// this routine is called.

#ifdef USE_LCD_RW
int8 lcd_read_nibble(void)
{
int8 retval;
// Create bit variables so that we can easily set
// individual bits in the retval variable.
#bit retval_0 = retval.0
#bit retval_1 = retval.1
#bit retval_2 = retval.2
#bit retval_3 = retval.3

retval = 0;

output_high(LCD_E);
delay_cycles(1);

retval_0 = input(LCD_DB4);
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);

output_low(LCD_E);

return(retval);
}
#endif

//---------------------------------------
// Read a byte from the LCD and return it.

#ifdef USE_LCD_RW
int8 lcd_read_byte(void)
{
int8 low;
int8 high;

output_high(LCD_RW);
delay_cycles(1);

high = lcd_read_nibble();

low = lcd_read_nibble();

return( (high<<4) | low);
}
#endif

//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(int8 address, int8 n)
{
output_low(LCD_RS);

#ifdef USE_LCD_RW
while(bit_test(lcd_read_byte(),7)) ;
#else
delay_us(60);
#endif

if(address)
output_high(LCD_RS);
else
output_low(LCD_RS);

delay_cycles(1);

#ifdef USE_LCD_RW
output_low(LCD_RW);
delay_cycles(1);
#endif

output_low(LCD_E);

lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}

//----------------------------
void lcd_init(void)
{
int8 i;

output_low(LCD_RS);

#ifdef USE_LCD_RW
output_low(LCD_RW);
#endif

output_low(LCD_E);

delay_ms(15);

for(i=0 ;i < 3; i++)
{
lcd_send_nibble(0x03);
delay_ms(5);
}

lcd_send_nibble(0x02);

for(i=0; i < sizeof(LCD_INIT_STRING); i++)
{
lcd_send_byte(0, LCD_INIT_STRING[i]);

// If the R/W signal is not used, then
// the busy bit can't be polled. One of
// the init commands takes longer than
// the hard-coded delay of 60 us, so in
// that case, lets just do a 5 ms delay
// after all four of them.
#ifndef USE_LCD_RW
delay_ms(5);
#endif
}

}

//----------------------------

void lcd_gotoxy(int8 x, int8 y)
{
int8 address;

if(y != 1)
address = lcd_line_two;
else
address=0;

address += x-1;
lcd_send_byte(0, 0x80 | address);
}

//-----------------------------
void lcd_putc(char c)
{
switch(c)
{
case '\f':
lcd_send_byte(0,1);
delay_ms(2);
break;

case '\n':
lcd_gotoxy(1,2);
break;

case '\b':
lcd_send_byte(0,0x10);
break;

default:
lcd_send_byte(1,c);
break;
}
}

//------------------------------
#ifdef USE_LCD_RW
char lcd_getc(int8 x, int8 y)
{
char value;

lcd_gotoxy(x,y);

// Wait until busy flag is low.
while(bit_test(lcd_read_byte(),7));

output_high(LCD_RS);
value = lcd_read_byte();
output_low(lcd_RS);

return(value);
}
#endif
// flex_lcd.c

Código fonte para o 16F628A:


Programa teste para fazer um relógio com o 16F877A
Implementada funções que mostram data e dia da semana
Teste promo_version v1.1
by MatheusLPS (Koala)
=============================================================================*/

#include <16F628A.h> //O PIC utilizado, obrigatório!
#FUSES NOWDT //Sem Watch dog, evitando reset
#FUSES XT //Crystal de oscilação igual a 4mhz
#FUSES PUT //Tempo de início do PIC
#FUSES NOPROTECT //Codigo sem proteção de leitura, software livre!
//#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection


#use delay(clock=4000000) // Definição do clock utilizado. Obrigatório!

#include <lcd_flex.C> //Inclusão da biblioteca de LCD. Obrigatório!

/*=====================
Meu Botões:
=======================*/

#define BOTAO1 PIN_A0 //Botão de escolha de ajuste das funçoes.
#define BOTAO_INCREMENTO PIN_A1 //Botão incremento de variáveis.
#define BOTAO_DECREMENTO PIN_A2 //Botão de decremento das variáveis.
//Foram utilizados resistores pull-up e
//pull-down em todos os botões para
//evitar ruídos.

/*=====================
Minhas variáveis:
=======================*/

int16 q=0; //Variável que incrementa a cada 0.5s dentro da interupção do timer1.
int s=0; //Variável dos segundos, incrementa na metade de q.
int m=0; //Variável dos minutos. 0 a 59
int h=0; //Variável das horas. 0 a 23.
int contador=0; //Variável de controle do botão de ajuste.
int ndia_semana=1; //Variável dos dias da semana, é associada a uma string.
int dia=1; //Variável dos dias do mês. 0 a 31.
int mes=1; //Variável dos meses. 0 a 12.
int16 ano=2010; //Variável dos anos. 2000 a 2099.

/*=====================
Minha Interrupção:
=======================*/

#int_TIMER1 //Interrupção do Timer1
void temp1s(void) //Funcão. O que deverá ser feiro a cada interrupão.
{
q++; //Variável q incrementada a cada estouro do Timer1
set_timer1 (3036); //Preload do Timer1
}

/*=====================
O programa Principal:
=======================*/
void main()
{
lcd_init(); //Inicializa o LCD (obrigatório)!


setup_timer_1 (T1_INTERNAL | T1_DIV_BY_8); //Configuração do Timer1 para clock interno = 1E6 dividido por 8
set_timer1 (3036); //Preload do Timer1
enable_interrupts(INT_TIMER1); //Habilita interrupção timer1
enable_interrupts(global); //habilita interrupcão global

while(TRUE) //Loop Principal
{
/*=====================================================================
Teste do botão de ajuste. A medida que é precionado, a variável contador
incrementa e as diversas funções de ajustes podem ser efetuadas. São 6
funções de ajuste, HORA, MINUTO, DIA DA SEMANA,DIA DO MES, MÊS e ANO. A
cada ajuste de uma função, o menu principal com todas as informações é
mostrado.
=====================================================================*/

if (input(BOTAO1)) //Teste do botão.
{
delay_ms (100); //Para evitar retorno.
if (contador>11) //Se maior q 11, zera o contador.
{
contador=0;
}

contador++; //Incremento da variável contador.
}

switch (contador) //Depois de incrementada, a variável CONTADOR
{ //assume um dos casos a seguir:
case 1: //Menu de ajuste da HORA.
{
if (input (BOTAO_INCREMENTO)) //Incrementa a variável H(hora).
{
delay_ms (75);
h++;

if (h>23) //Se a hora for maior que 23, reset.
{
h=0;
}
}

if (input (BOTAO_DECREMENTO)) //Decrementa a variável H(hora).
{
delay_ms (75);
h--;

if (h==255) //H é uma variável inteira de 8 bits.
{ //Quando é decrementada para um valor
h=23; //menor que zero, se torna 255. Ou seja,
} //deve voltar para 23.
}

q=0; //Quando se está em algum menu, Q é resetada.
lcd_gotoxy (1,1); //Vá para a coluna 1 e linha 1 do LCD.
printf (lcd_putc, "\fAjuste Hora:%02u", h); //Escreva com 2 digitos a variável H.
delay_ms (100); //Mantenha na tela.
break;
}

case 3: //Menu de ajuste do MINUTO. Idem ao anterior.
{
if (input (BOTAO_INCREMENTO))
{
delay_ms (75);
m++;

if (m>59) //Diferente aqui.
{
m=0;
}
}

if (input (BOTAO_DECREMENTO))
{
delay_ms (75);
m--;

if (m==255) //Igual aqui.
{
m=59;
}
}

q=0;
lcd_gotoxy (1,1);
printf (lcd_putc, "\fAjuste Minuto:%02u", m);
delay_ms (100);
break;
}

case 5: //Menu de ajuste do DIA DA SEMANA.
{
/*=====================================================================
Ajuste do DIA DA SEMANA. A função ficou meio bagunçada. Pesquisarei
um pouco sobre como trasformar uma string numa variável. Só
consegui fazer isso com 1 (um) caracter, mas não é o ideal. Depois disso,
provavelmente essa parte ficará mais enxuta.

A função ficou assim: Uma variável chamada ndia_semana(número dia da
semana) é incrementada de 1 a 7. Cada número é associado a um dia da
semana. 1 é Domingo, 2 é Segunda e assim por diante. Se ndia_semana for
maior que 7, ela é resetada em 1 de novo. Utilizei a função SWITCH para
associar cada número de 1 a 7 a cada dia da semana.
=====================================================================*/
if (input (BOTAO_INCREMENTO))
{
delay_ms (100);
ndia_semana++;
if (ndia_semana>7)
{
ndia_semana=1;
}

}

if (input (BOTAO_DECREMENTO))
{
delay_ms (75);
ndia_semana--;
if (ndia_semana==255)
{
ndia_semana=7;
}
}

switch (ndia_semana)
{
case 1:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "\fDia da Semana:\nDomingo ");
delay_ms (100);
break;
}

case 2:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "\fDia da Semana:\nSegunda ");
delay_ms (100);
break;
}

case 3:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "\fDia da Semana:\nTerca ");
delay_ms (100);
break;
}

case 4:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "\fDia da Semana:\nQuarta ");
delay_ms (100);
break;
}

case 5:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "\fDia da Semana:\nQuinta ");
delay_ms (100);
break;
}

case 6:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "\fDia da Semana:\nSexta ");
delay_ms (100);
break;
}

case 7:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "\fDia da Semana:\nSabado ");
delay_ms (100);
break;
}
}

q=0; //Variável q sempre resetada nos menus.
break;
}

case 7: //Menu de ajuste do DIA DO MES. Idem ao caso 3.
{
if (input (BOTAO_INCREMENTO))
{
delay_ms (100);
dia++;
if (dia>31)
{
dia=1;
}

}

if (input (BOTAO_DECREMENTO))
{
delay_ms (75);
dia--;
if (dia==0)
{
dia=31;
}
}

q=0;
lcd_gotoxy (1,1);
printf (lcd_putc, "\fAjuste dia Mes: \n%02u", dia);
delay_ms (100);
break;
}

case 9: //Menu de ajuste do MES. Idem ao caso 3.
{
if (input (BOTAO_INCREMENTO))
{
delay_ms (100);
mes++;
if (mes>12)
{
mes=1;
}

}

if (input (BOTAO_DECREMENTO))
{
delay_ms (75);
mes--;
if (mes==0)
{
mes=12;
}
}

q=0;
lcd_gotoxy (1,1);
printf (lcd_putc, "\fAjuste Mes: \n%02u", mes);
delay_ms (100);
break;
}

case 11: //Menu de ajuste do ANO. Idem ao caso 3.
{
if (input (BOTAO_INCREMENTO))
{
delay_ms (100);
ano++;
if (ano>2099)
{
ano=2000;
}

}

if (input (BOTAO_DECREMENTO))
{
delay_ms (75);
ano--;
if (ano==1999)
{
ano=2099;
}
}

q=0;
lcd_gotoxy (1,1);
printf (lcd_putc, "\fAjuste Ano: \n%Lu", ano);
delay_ms (100);
break;
}

default: //Menu principal. Mostra todas as informações.
{
s=q/2; //A variável Q incrementa a 2Hz, então os segundos
//devem ser a metade.
if (s==60) //Se for igual a 60, reset em Q e S. M incrementa.
{
q=0;
s=0;
m++;
}

if (m>59)
{
m=0;
h++;
}

if (h>23) //Se H(horas) for maior q 23, reset. DIA DA SEMANA
{ //e DIA DO MÊS incrementam.
dia++;
ndia_semana++;
h=0;
}

if (ndia_semana>7)
{
ndia_semana=1;
}

switch (ndia_semana) //Os DIAS DA SEMANA só alteram sozinhos no menu
{ //principal. Idem ao caso 5.
case 1:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "DOMINGO ");
delay_ms (100);
break;
}

case 2:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "SEGUNDA ");
delay_ms (100);
break;
}

case 3:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "TERCA ");
delay_ms (100);
break;
}

case 4:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "QUARTA ");
delay_ms (100);
break;
}

case 5:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "QUINTA ");
delay_ms (100);
break;
}

case 6:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "SEXTA ");
delay_ms (100);
break;
}

case 7:
{
lcd_gotoxy (1,1);
printf (lcd_putc, "sábado ");
delay_ms (100);
break;
}
}

switch (mes) //Para saber se um mês possui 31, 30 ou 28 dias.
{ //Numa versão mais nova, farei essa rotina mais enxuta.
case (1):
{
if (dia>31)
{
dia=1;
mes++;
}
break;
}

case 2:
{
if (dia>28)
{
dia=1;
mes++;
}
break;
}

case (3):
{
if (dia>31)
{
dia=1;
mes++;
}
break;
}

case (4):
{
if (dia>30)
{
dia=1;
mes++;
}
break;
}

case (5):
{
if (dia>31)
{
dia=1;
mes++;
}
break;
}

case (6):
{
if (dia>30)
{
dia=1;
mes++;
}
break;
}

case (7):
{
if (dia>31)
{
dia=1;
mes++;
}
break;
}

case (8):
{
if (dia>31)
{
dia=1;
mes++;
}
break;
}

case (9):
{
if (dia>30)
{
dia=1;
mes++;
}
break;
}

case (10):
{
if (dia>31)
{
dia=1;
mes++;
}
break;
}

case (11):
{
if (dia>30)
{
dia=1;
mes++;
}
break;
}

case (12):
{
if (dia>31)
{
dia=1;
mes=1;
ano++;
}
break;
}
}

lcd_gotoxy (9,1);
printf (lcd_putc, "%02u:%02u:%02u\n%02u/%02u/%Lu Koala", h, m, s, dia, mes, ano);
delay_ms (100);
break;
}
}
}
}
/*=============================================================================

Foto com 16F877A:

ss102247.jpg

Qualquer dúvida posta aí, Falou.

Editado por MatheusLPS

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

Entre para seguir isso  





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

×