Sugestão de implementação
Tecla # Entra e sai do ajuste do relogio
Tecla 2 (^) rola o menu de opções para cima
Tecla 8 (v) rola o menu de opções para baixo
Tecla 4 (<) Ajusta a opção corrente do menu por decremento
Tecla 6 (>) Ajusta a opção corrente do menu por incremento
Opções do menu e ajustes possíveis:
1 - Dia corrente (SUN, MON, TUE, WED, THU, FRI, SAT)
2 - Data (1 a 31)
3 - Mês (1 a 12)
4 - Ano (2000 a 2099)
5 - Hora (0 a 23)
6 - Minutos (0 a 59)
Sugestão de variáveis a ser utilizadas
Leitura, gravação e apresentação do lcd
- sec
- min
- hour
- day
- date
- month
- year
Ajuste dos parâmetros
- min_aj
- hour_aj
- day_aj
- date_aj
- month_aj
- year_aj
Controle e fluxo de programa
tec // valor do código ASCII da tecla pressionada
fl_tec // flag que indica que uma tecla foi pressionada, valores 1 (uma tecla foi pressionada) ou 0
menu // indica a opção corrente que será mostrada no LCD e pode ser alterada
fl_menu // indica que está no modo de ajuste, valores 0 ou 1, serve para manter um while () que
executa o ajuste do menu
Funções para modificar os dados RTC - > ajuste
// devolve a dezena em decimal do numero
unsigned char UpperCh(unsigned char ch)
{
unsigned char temp;
temp = ch >> 4;
return(temp);
}
// devolve a unidade em decimal do numero
unsigned char LowerCh(unsigned char ch)
{
unsigned char temp;
temp = ch & 0x0F; //Making the Upper 4-bits
return(temp);
}
Exemplo de uso:
unsignde char min; // variável usada para ler os minutos do RTC
unsigned char min_aj; // variável para fazer o ajuste dos minutos
min_aj = UpperCh(min)*10 + LowerCh(min);
Funções para modificar os dados Ajuste -> RTC
// converte para o formato RTC
unsigned char ch_to_rtc (unsigned char ch){
unsigned char dezena,unidade,saida;
dezena = ch/10; // dezena
unidade= ch - dezena*10; // unidade
saida = (dezena<<4)|(unidade);
// temp = ((ch/10)<<4) && (ch - (ch/10)); // não sei se funciona de uma vez só???
return saida;
}
Exemplo de uso:
unsignde char min; // variável usada para ler os minutos do RTC
unsigned char min_aj; // variável para fazer o ajuste dos minutos
min = ch_to_rtc(min_aj);
Programa com funções a completar
/*
*
* Programa que mostra caledário e relógio no LCD
* Teclado matricila por conversor AD com Interrupção
* Programa de ajuste do relógio
*
* Tecla # Entra e sai do ajuste do relogio
* Tecla 8 (^) rola o menu de opções para cima
* Tecla 2 (v) rola o menu de opções para baixo
* Tecla 4 (<) Ajusta a opção corrente do menu por decremento
* Tecla 6 (>) Ajusta a opção corrente do menu por incremento
*
* Opções do menu e ajustes possíveis:
* 1 - Dia corrente (SUN, MON, TUE, WED, THU, FRI, SAT)
* 2 - Data (1 a 31)
* 3 - Mes (1 a 12)
* 4 - Ano (2000 a 2099)
* 5 - Hora (0 a 23)
* 6 - Minutos (0 a 59)
*
*/
#define _XTAL_FREQ 48000000
#include <xc.h>
#include <stdio.h>
#include "C:\h\config_PIC18F4550.h"
#include "c:\h\biblioteca_lcd_2x162_48M_XC.h"
// prototipos de funções para leitura e escrita do rtc i2c
void i2c_init();
void i2c_start(void);
void i2c_restart(void);
void i2c_stop(void);
void i2c_wait(void);
void i2c_send(unsigned char dat);
unsigned char i2c_read(void);
unsigned char rtc1307_read(unsigned char address);
//RTC DS1307 Read Function
// protipos de funções para o main e funcionamento do teclado matriacial
void inicia_regs(void);
void interrupt ISR_alta_prioridade(void);
void config_int(void);
void config_int2 (void);
void config_AD(void);
int conv_AD(void);
void delay_ms(int i);
void atraso_meios(unsigned char meio_segundos);
unsigned char UpperCh(unsigned char ch);
unsigned char LowerCh(unsigned char ch);
unsigned char ch_to_rtc (unsigned char ch);
void grava_rtc (void);
void mostra_rtc_lcd(void);
void mostra_menu(void);
void trata_tecla_4(void);
void trata_tecla_6(void);
void trata_tecla_8(void);
void trata_tecla_2(void);
unsigned char fl_tec = 0, tec = 0;
/* fl_tec: flag que indica que chegou uma tecla
* tec: valor asc da tecla recebida
*/
unsigned char sec,min,hour,day,date,month,year, menu=1;
unsigned char min_aj,hour_aj,day_aj,date_aj,month_aj,year_aj;
unsigned char buffer[17];
void main(void) {
unsigned char fl_menu = 0;
inicia_regs();
config_int();
config_int2(); // configura as interrupções
config_AD(); // configura e inicializa o conversor AD
i2c_init(); //To Generate the Clock of 100Khz
// trata o LCD
lcd_inicia(0x28, 0x0f, 0x06); // incializa o LCD com 4 linhas
lcd_LD_cursor(0); // Desliga o cursor
lcd_posicao(1, 1);
imprime_string_lcd(" Calendario ");
lcd_posicao(2, 1);
imprime_string_lcd(" Relogio - RTC ");
atraso_meios(2);
while (1) {
lcd_posicao(2, 1);
imprime_string_lcd("Set-RTC press #");
mostra_rtc_lcd();
if (fl_tec) {
fl_tec = 0;
if (tec == 35) {// tecla # entra no mneu
fl_menu = 1;
// converte os dados para numero para ajuste
// sec_aj = UpperCh(sec)*10 + LowerCh(sec);
min_aj = UpperCh(min)*10 + LowerCh(min);
hour_aj = UpperCh(hour)*10 + LowerCh(hour);
day_aj = day;
date_aj = UpperCh(date)*10 + LowerCh(date);
month_aj = UpperCh(month)*10 + LowerCh(month);
year_aj = UpperCh(year)*10 + LowerCh(year);
mostra_menu();
// fim da conversão
}
}
while (fl_menu) {
if (fl_tec) {
fl_tec = 0;
if (tec == 35) { // tecla # sai do menu
fl_menu = 0;
tec = 0; // destrava o while do menu
grava_rtc(); // grava os dados no rtc
}
trata_tecla_8();
trata_tecla_2();
trata_tecla_4();
trata_tecla_6();
mostra_menu();
}
}
}
}
// funções para leitura e escrita do rtc i2c
// copiar as funções do programa de exemplo
// void i2c_init(){}
// void i2c_start(void){}
// void i2c_restart(void){}
// void i2c_stop(void){}
// void i2c_wait(void){}
// void i2c_send(unsigned char dat){}
//unsigned char i2c_read(void){}
unsigned char rtc1307_read(unsigned char address)
{
unsigned char temp;
i2c_start();
i2c_send(0xD0);
i2c_send(address);
i2c_restart();
i2c_send(0xD1);
temp = i2c_read();
//i2c_stop();
this line is Removed Because it is already included in i2c_read function
return temp;
}
// fim das funções para leitura e escrita do rtc i2c
// funções para o main e funcionamento do teclado materiacial
// função de configuração do conversor A/D
// void config_AD(void) {}
// função que efeuta uma conversão A/D e retorna um inteiro com o valor convertido
// int conv_AD(void) {}
// função que inicia os registradores I/O
//
void inicia_regs(void) {}
// função de interrupção de alta prioridade
// função que lê o teclado na INT2 - Ver prog cofre
//
void interrupt ISR_alta_prioridade(void) {}
// função de configuração geral de interrupções
//
void config_int(void) {}
// configura a interrupção exarna INT2
//
void config_int2(void) {}
// função que gera atraso em mlisegundos
//
void delay_ms(int i){}
//função de atraso de multiplos de 0,5s
//
void atraso_meios(unsigned char meio_segundos)
// devolve a dezena em decimal do numero
unsigned char UpperCh(unsigned char ch)
{
unsigned char temp;
temp = ch >> 4;
return(temp);
}
// devolve a unidade em decimal do numero
unsigned char LowerCh(unsigned char ch)
{
unsigned char temp;
temp = ch & 0x0F; //Making the Upper 4-bits
return(temp);
}
// converte para o formato RTC
unsigned char ch_to_rtc (unsigned char ch){
unsigned char dezena,unidade,saida;
dezena = ch/10; // dezena
unidade= ch - dezena*10; // unidade
saida = (dezena<<4)|(unidade);
// temp = ((ch/10)<<4) && (ch - (ch/10)); // não sei se funciona de uma vez só???
return saida;
}
// grava os dados no RTC
/* void grava_rtc(void) {
// retorna os alores para gravação
min = ch_to_rtc(min_aj);
// fazer para hour, day, date, month, year
// rotina de gravação
// exemplo para gravação de um valor fixo
// data quarta 31/dez/2014 23h 59min e 45 seg
// i2c_start();
// i2c_send(0xD0);
// i2c_send(0x00);
// i2c_send(0x45 | 0x80); //CH = 1 Stop oscillator
// i2c_send(0x59); //Minute
// i2c_send(0x23); //Hour
// i2c_send(0x04); //4 - quarta
// i2c_send(0x31); //31 data
// i2c_send(0x12); //12 Dez
// i2c_send(0x14); //2014
// i2c_stop(); //Stop the I2C Protocol
//Have to start the Clock again
// i2c_start();
// i2c_send(0xD0);
// i2c_send(0x00);
// i2c_send(0x00); //start Clock and set the second hand to Zero
// i2c_stop();
// fim do start
}
// mostra caledario - hora alternados na linha 1
void mostra_rtc_lcd(void){
sec = rtc1307_read(0x00);
// ler min, hour, day, date, month, year
lcd_posicao(1, 1);
switch (day) {
case 1: sprintf(buffer, "SUN %02x/%02x/20%02x", date, month, year);
break;
// fazer para os outros 6 dias da semana
}
imprime_buffer_lcd(buffer, 15);
atraso_meios(1);
// mostra a hora na na linha 1 e espera 1/2 segundo
}
void mostra_menu(void) {
/*1 - Dia corrente (SUN, MON, TUE, WED, THU, FRI, SAT)
* 2 - Data (1 a 31)
* 3 - Mes (1 a 12)
* 4 - Ano (2000 a 2099)
* 5 - Hora (0 a 23)
* 6 - Minutos (0 a 59) */
// lcd_limpa_tela();
switch (menu) {
case 1:
switch (day_aj) {
case 1: sprintf(buffer, "dia = SUNDAY ");
break;
// fazer os outros dias
}
break;
case 2:
sprintf(buffer, " Data = %2d ", date_aj);
break;
// fazer para Mes, Ano, Hora, Minutos
}
lcd_posicao(1, 1);
imprime_buffer_lcd(buffer, 15);
lcd_posicao(2, 1);
imprime_string_lcd("set < > ch ^ v ");
}
void trata_tecla_4(void) {
if (tec == 52) {// tecla 4 < decrementa a opção corrente
switch (menu) {
case 1: // decrementa dia
day_aj--;
if (day_aj == 0) {
day_aj = 7;
}
break;
case 2: // decrementa data
if (date_aj == 1) {
date_aj = 31;
} else date_aj--;
break;
case 3: // decrementa mês
if (month_aj == 1) {
month_aj = 12;
}
month_aj--;
break;
case 4: // decrementa ano
if (year_aj == 0) {
year_aj = 99;
} else year_aj--;
break;
case 5: // decrementa hora
if (hour_aj == 0) {
hour_aj = 23;
} else hour_aj--;
break;
case 6: // decrementa minutos
if (min_aj == 0) {
min_aj = 59;
} else min_aj--;
break;
}
}
}
void trata_tecla_6(void) {
// ver exemplo função trata_tecla_4
}
void trata_tecla_8(void) {
if (tec == 56) {// tecla 8 ^ rola menu p/ cima
if (menu < 6) {
menu++;
} else {
menu = 1;
}
}
}
void trata_tecla_2(void) {
// ver exemplo função trata_tecla_8
}