Calendario do DS1307

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Calendario do DS1307

Mensagempor buiz » 03 Mai 2008 11:37

Olá,

Estou com o seguinte problema para resolver, tenho um equipamento que trabalha com o DS1307 para obter data e hora.

Tenho que fazer um calendario com os dias da semana, hoje o equipamento trabalha mostrando a hora = 12:00 e data 01/01/2008, tenho que mostrar os dias da semana, SEG, TER, QUA, QUI, SEX, SAB e DOM.

Como posso fazer isso, programo em C, e utilizei o PIC18F452 neste meu projeto e um DS1307 para hora e data.

Grato a quem me ajudar.

Buiz
Avatar do usuário
buiz
Byte
 
Mensagens: 165
Registrado em: 20 Out 2006 14:59
Localização: Cachoeira do Sul - RS

Re: Calendario do DS1307

Mensagempor Jorge_Francisco » 03 Mai 2008 12:05

A ideia é essa abaixo, este código uso em C++, é só fazer uma adaptação:


Código: Selecionar todos

int A,B,C,D,E,F,Ano,Mes,Dia,Dia_Juliano;

String Dia_Semana[7]={"Segunda-feira","Terça-feira","Quarta-feira",
"Quinta-feira","Sexta-feira","Sábado","Domingo"};


Ano = 2008;
Mes = 05;
Dia = 03;

if( Mes < 3 )
{
 Ano = Ano - 1;
 Mes = Mes + 12;
}



A = Ano/100;
B = A/4;
C = 2 - A + B;

//Se a data for igual ou anterior a 4/10/1582 (fim do Calendário Juliano):
//C = 0

if(Dia <= 4 && Mes <= 10 && Ano <= 1582)
C=0;

D = 365.25 * (Ano + 4716);
E = 30.6001 * (Mes + 1);

Dia_Juliano = D + E + Dia + C - 1524;

NomeDia = Dia_Semana[Dia_Juliano%7];



Vlw
Avatar do usuário
Jorge_Francisco
Dword
 
Mensagens: 1009
Registrado em: 12 Out 2006 09:53
Localização: Rio de Janeiro

Mensagempor RobL » 03 Mai 2008 14:33

Penso que isso ele já tem dentro do DS1307
A questão é que ele pega os dias da semana com 1,2,3...7 e quer escrever
1 <=> dom; 2<=> seg; ...
Use a função case com o valor do dia da semana que pegou no DS1307.

case dia_da_semana (tipo inteiro) que você pegou do DS1305
1 - semana = dom (string)
2 - semana = seg
...

Não esquecer de definir uma variável string para os dias da semana.

Espero que seja isso.
RobL
Dword
 
Mensagens: 1546
Registrado em: 20 Fev 2007 17:56

Mensagempor RobL » 03 Mai 2008 14:43

Quero dizer: Use o comando Switch / case
RobL
Dword
 
Mensagens: 1546
Registrado em: 20 Fev 2007 17:56

Mensagempor Jorge_Francisco » 03 Mai 2008 15:00

Acho que só retorna :

HH:MM:SS YY-MM-DD

Então a função que coloquei aqui funciona.

Vlw
Avatar do usuário
Jorge_Francisco
Dword
 
Mensagens: 1009
Registrado em: 12 Out 2006 09:53
Localização: Rio de Janeiro

Mensagempor RobL » 03 Mai 2008 15:53

O DS1307 retorna DAY e DATE.
DAY é o dia da semana em bcd coincide com binário (int) não passa de 7.
DATE é o dia do mes em BCD não conincide com binário pois passa de 0xF.
Se é o que entendí basta pegar sua variável DAY e criar uma função usando o comand Switch / case conforme acima.
RobL
Dword
 
Mensagens: 1546
Registrado em: 20 Fev 2007 17:56

Mensagempor Maurício » 03 Mai 2008 18:10

É só usar a variável DAY, pra indexar um vetor de strings:

Código: Selecionar todos
char dias_semana [7][4] = "SEG", "TER", "QUA", "QUI", "SEX", "SAB", "DOM";


printf ( "Hoje eh: %s", dia_semana[DAY] );


Só precisa confirmar se a variável DAY começa com 1 ou com zero e que o primeiro dia seja DOM ou SEG.

Se começar com 1, então é preciso subtrair 1 da variável DAY pra ela poder indexar corretamente o vetor:

Código: Selecionar todos
printf ( "Hoje eh: %s", dia_semana[DAY-1] );


[]'s
"Não leve a vida tão à sério, afinal, nenhum de nós sairá vivo, dela!"
Avatar do usuário
Maurício
Word
 
Mensagens: 678
Registrado em: 14 Out 2006 17:23
Localização: São Paulo - SP

Mensagempor Jorge_Francisco » 03 Mai 2008 20:25

Ja que existe a variavel DAY realmente não precisa do meu código, é que não foi informado isso,hehehe.
Avatar do usuário
Jorge_Francisco
Dword
 
Mensagens: 1009
Registrado em: 12 Out 2006 09:53
Localização: Rio de Janeiro

Mensagempor ze » 05 Mai 2008 08:09

Código: Selecionar todos
...
...
const char* dsem[] = "Domingo","Segunda","Terca  ","Quarta ","Quinta ","Sexta  ","Sabado "; //dsem[0...6]=string
...
...

obs:
ds1307:dado diasem:1 a 7 (!) =>index-=1 => if (index>6) index=0 : proteção inicial anti estouro do index pro caso de leitura diasem

abrç
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Mensagempor buiz » 05 Mai 2008 09:57

Olá pessoal,

Estou analisando todas as dicas aqui postadas, ainda não tive tempo de testar pois estou de recuperação de uma gripe fortissima que me atingiu.

Assim que retornar ao trabalho normal vou analisar dica por dica para achar uma solução, desde já agradeço ao Lellis, Jorge, Mauricio e Robt que postaram aqui até o momento.

Valeu!!!!!!

Um abraço e uma ótima semana a todos.
Avatar do usuário
buiz
Byte
 
Mensagens: 165
Registrado em: 20 Out 2006 14:59
Localização: Cachoeira do Sul - RS

Mensagempor buiz » 13 Mai 2008 14:00

Reportando,

Ok, funcionou segundo as informações do Mauricio, meu problema maior foi acessar os dias dentro do DS1307, depois tudo correu bem!

Código: Selecionar todos
char dias_semana [7][4] = "SEG", "TER", "QUA", "QUI", "SEX", "SAB", "DOM";


printf ( "Hoje eh: %s", dia_semana[DAY-1] );


Valeu e obrigado a todos!
Avatar do usuário
buiz
Byte
 
Mensagens: 165
Registrado em: 20 Out 2006 14:59
Localização: Cachoeira do Sul - RS

Mensagempor SoMeWhErE » 14 Mai 2008 12:16

Ola.

Estou mexendo tambem com DS1307, mas não estou conseguindo fazer funcionar, tenho um programa exemplo aqui, mas ele não está funcionando. Estou usando PIC18F452 e MikroC.

O programa inicia o DS1307 com alguns valores, e depois em intervalos de 200ms le e atualiza o display. Só que esta aparecendo o seguinte no dislpay:

Config:
HH:MM:SS DIA_SEMANA
DD/MM/AAAA

O que exibe é o seguinte:
??: ??:=0 SABADO
??/??/20??

o 20 aparece pq esta sendo exibido direto, e o sabado pois na função de encontrar dia da semana atraves do switch-case tem de 1 a 6 e o sabado foi posto como default.

Código: Selecionar todos
void programa_i2c(){
I2C_Init(100000); // iniciliza I2C com frequencia de 100KHz
I2C_Start(); //inicializa a comunicação I2c
I2C_Wr(0xD0); //endereço fixo para a categoria do DS1307: 1101000X, onde x = 0 é para gravação, e X = 1 para leitura.
I2C_Wr(0);  //endereço onde iremos começar a programação do relógio, neste caso é o endereço dos segundos.
I2C_Wr(0x25);  //inicializa a contagem dos segundos apartir de 25.
I2C_Wr(0x44);  //inicializa a contagem a partir de 44 minutos.
I2C_Wr(0x08);  //inicializa a contagem das 08:00hs (formato 24 horas).
I2C_Wr(0x06);  //inicializa a contagem da sexta feira da semana
I2C_Wr(0x14);  //inicializa a contagem do dia 14 do mes
I2C_Wr(0x10);  //inicializa a contagem do mês de setembro
I2C_Wr(0x07);  //inicializa a contagem do ano 07.
I2C_Stop();    //condição de finalização da comunicação I2C
}

void leitura_rtc() {   //rotina de leitura do DS1307

I2C_Start();  //inicializa comunicação i2c
I2C_Wr(0xD0); //endereço fixo para a categoria do DS1307: 1101000X, onde x = 0 é para gravação, e X = 1 para leitura.
I2C_Wr(0);  //endereço onde iremos começar a programação do relógio, neste caso é o endereço dos segundos.
I2C_Repeated_Start(); // Issue I2C signal repeated start
I2C_Wr(0xD1); //endereço fixo para a categoria do DS1307: 1101000X com o ultimo bit acionado (1) para leitura
segundo = I2C_Rd(1); //lê o primeiro byte segundos e informa que ainda leremos mais dados através do sinalizador (1)
minuto = I2C_Rd(1); //lê o segundo byte minutos e informa que ainda leremos mais dados através do sinalizador (1)
horas = I2C_Rd(1);
dias_semana = I2C_Rd(1);
dia = I2C_Rd(1);
mes = I2C_Rd(1);
anos = I2C_Rd(0); //lê o setimo byte horas e encerra as leituras de dados, graças ao sinalizador (0)
I2C_Stop();   //finaliza comunicação I2C
}


ae esta a função de inicialização e leitura do DS1307.

Valews
Avatar do usuário
SoMeWhErE
Byte
 
Mensagens: 119
Registrado em: 20 Jun 2007 18:09
Localização: Charqueada

Mensagempor buiz » 14 Mai 2008 14:10

Olá,

Eu utilizo esta biblioteca para o DS1307, só que programo no CCS, da uma olhada e ve se consegue adaptar para o MiKroC.

Código: Selecionar todos

//////////////////////////////////////////////////////////////////
//Biblioteca para uso do DS1307
//Data: 20/02/2007
//Alterações: Buiz
///////////////////////////////////////////////////////////////////

#define RTC_SDA PIN_c4
#define RTC_SCL PIN_c3

#define DS1307_I2C_WRITE_ADDR 0xd0
#define DS1307_I2C_READ_ADDR 0xd1

#use i2c(master, sda=RTC_SDA, scl=RTC_SCL)

BYTE bin2bcd(BYTE binary_value);
BYTE bcd2bin(BYTE bcd_value);



void ds1307_init(void)
{
BYTE seconds = 0;

i2c_start();
i2c_write(0xD0); // WR to RTC
i2c_write(0x00); // REG 0
i2c_start();
i2c_write(0xD1); // RD from RTC
seconds = bcd2bin(i2c_read(0)); // Read current "seconds" in DS1307
i2c_stop();
seconds &= 0x7F;

delay_us(3);

i2c_start();
i2c_write(0xD0); // WR to RTC
i2c_write(0x00); // REG 0
i2c_write(bin2bcd(seconds)); // Start oscillator with current "seconds value
i2c_start();
i2c_write(0xD0); // WR to RTC
i2c_write(0x07); // Control Register
i2c_write(0x80); // Disable squarewave output pin
i2c_stop();

}


//------------------------------------------------------------------------
// Read one byte at the specified address.
// This function is used to access the control byte
// or the NVRAM bytes.

char le_ds1307(char addr)
{
char retval;

disable_interrupts(GLOBAL);
i2c_start();
i2c_write(DS1307_I2C_WRITE_ADDR);
i2c_write(addr);

i2c_start();
i2c_write(DS1307_I2C_READ_ADDR);
retval = i2c_read(0); // Don't ACK the last byte read
i2c_stop();
enable_interrupts(GLOBAL);

return(retval);
}

//----------------------------------------------------------------------
// Write one byte to the DS1307.
// This function is used to access the control byte
// or the NVRAM bytes.

void escreve_ds1307(char addr, char value)
{
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(DS1307_I2C_WRITE_ADDR);
i2c_write(addr);
i2c_write(value);
i2c_stop();
enable_interrupts(GLOBAL);
}
//-------------------------------------------------------------




void ds1307_set_date_time(BYTE day, BYTE mth, BYTE year, BYTE dow, BYTE hr, BYTE min, BYTE sec)
{
sec &= 0x7F;
hr &= 0x3F;

i2c_start();
i2c_write(0xD0); // I2C write address
i2c_write(0x00); // Start at REG 0 - Seconds
i2c_write(bin2bcd(sec)); // REG 0
i2c_write(bin2bcd(min)); // REG 1
i2c_write(bin2bcd(hr)); // REG 2
i2c_write(bin2bcd(dow)); // REG 3
i2c_write(bin2bcd(day)); // REG 4
i2c_write(bin2bcd(mth)); // REG 5
i2c_write(bin2bcd(year)); // REG 6
i2c_write(0x80); // REG 7 - Disable squarewave output pin
i2c_stop();
}

void ds1307_get_date(BYTE &day, BYTE &mth, BYTE &year, BYTE &dow)
{
i2c_start();
i2c_write(0xD0);
i2c_write(0x03); // Start at REG 3 - Day of week
i2c_start();
i2c_write(0xD1);
dow = bcd2bin(i2c_read() & 0x7f); // REG 3
day = bcd2bin(i2c_read() & 0x3f); // REG 4
mth = bcd2bin(i2c_read() & 0x1f); // REG 5
year = bcd2bin(i2c_read(0)); // REG 6
i2c_stop();
}


void ds1307_get_time(BYTE &hr, BYTE &min, BYTE &sec)
{
i2c_start();
i2c_write(0xD0);
i2c_write(0x00); // Start at REG 0 - Seconds
i2c_start();
i2c_write(0xD1);
sec = bcd2bin(i2c_read() & 0x7f);
min = bcd2bin(i2c_read() & 0x7f);
hr = bcd2bin(i2c_read(0) & 0x3f);
i2c_stop();

}

BYTE bin2bcd(BYTE binary_value)
{
BYTE temp;
BYTE retval;

temp = binary_value;
retval = 0;

while(true)
{
// Get the tens digit by doing multiple subtraction
// of 10 from the binary value.
if(temp >= 10)
{
temp -= 10;
retval += 0x10;
}
else // Get the ones digit by adding the remainder.
{
retval += temp;
break;
}
}

return(retval);
}


// Input range - 00 to 99.
BYTE bcd2bin(BYTE bcd_value)
{
BYTE temp;

temp = bcd_value;
// Shifting upper digit right by 1 is same as multiplying by 8.
temp >>= 1;
// Isolate the bits for the upper digit.
temp &= 0x78;

// Now return: (Tens * 8) + (Tens * 2) + Ones

return(temp + (temp >> 2) + (bcd_value & 0x0f));
}


Testa ai, e posta o resultado! OK.

Buiz.
Avatar do usuário
buiz
Byte
 
Mensagens: 165
Registrado em: 20 Out 2006 14:59
Localização: Cachoeira do Sul - RS

Mensagempor Sergio38br » 14 Mai 2008 16:54

Boa tarde,
Pergunta capiciosa, o cristal de 32,768KHz esta funcionando?
Voce esta inicializando com os segundos, mas seria melhor vc iniciar na ordem inversa, sendo a primeira coisa o endereço 0x07(configuração que não vi no codigo), acerte tudo e depois grave o endereço 0x00 pois o bit 7 deste endereço inicia o oscilador interno quando levado a zero.

Sergio
Avatar do usuário
Sergio38br
Word
 
Mensagens: 759
Registrado em: 22 Nov 2007 13:39
Localização: São Paulo - SP

Mensagempor Sergio38br » 14 Mai 2008 17:35

modifiquei um pouco o código para o MikroC.

Código: Selecionar todos
void programa_i2c(){

I2C_Init(100000); // iniciliza I2C com frequencia de 100KHz
I2C_Start(); //inicializa a comunicação I2c
I2C_Wr(0xD0); //endereço fixo para a categoria do DS1307: 1101000X, onde x = 0 é para gravação, e X = 1 para leitura.
I2C_Wr(0x07); //endereço de configuração do DS1307
I2C_Wr(0b00010000);// CONFIGURADO PARA SAIDA SQWE COM A FREQUENCIA DE 1 Hz
I2C_Stop();

delay_ms(1);

I2C_Start(); //inicializa a comunicação I2c
I2C_Wr(0xD0); //endereço fixo para a categoria do DS1307: 1101000X, onde x = 0 é para gravação, e X = 1 para leitura.
I2C_Wr(0x01);  //endereço onde iremos começar a programação do relógio, neste caso é o endereço dos minutos.
I2C_Wr(0x44);  //inicializa a contagem a partir de 44 minutos.
I2C_Wr(0x08);  //inicializa a contagem das 08:00hs (formato 24 horas).
I2C_Wr(0x06);  //inicializa a contagem da sexta feira da semana
I2C_Wr(0x14);  //inicializa a contagem do dia 14 do mes
I2C_Wr(0x10);  //inicializa a contagem do mês de setembro
I2C_Wr(0x07);  //inicializa a contagem do ano 07.
I2C_Stop();    //condição de finalização da comunicação I2C

delay_ms(1);

I2C_Start(); //inicializa a comunicação I2c
I2C_Wr(0xD0); //endereço fixo para a categoria do DS1307: 1101000X, onde x = 0 é para gravação, e X = 1 para leitura.
I2C_Wr(0);  //endereço onde iremos começar a programação do relógio, neste caso é o endereço dos segundos.
I2C_Wr(0x25);  //inicializa a contagem dos segundos apartir de 25 e inicializar o oscilador interno
I2C_Stop();    //condição de finalização da comunicação I2C
}

void leitura_rtc() {   //rotina de leitura do DS1307

I2C_Start();  //inicializa comunicação i2c
I2C_Wr(0xD0); //endereço fixo para a categoria do DS1307: 1101000X, onde x = 0 é para gravação, e X = 1 para leitura.
I2C_Wr(0);  //endereço onde iremos começar a programação do relógio, neste caso é o endereço dos segundos.
I2C_Repeated_Start(); // Issue I2C signal repeated start
I2C_Wr(0xD1); //endereço fixo para a categoria do DS1307: 1101000X com o ultimo bit acionado (1) para leitura
segundo = I2C_Rd(1); //lê o primeiro byte segundos e informa que ainda leremos mais dados através do sinalizador (1)
minuto = I2C_Rd(1); //lê o segundo byte minutos e informa que ainda leremos mais dados através do sinalizador (1)
horas = I2C_Rd(1);
dias_semana = I2C_Rd(1);
dia = I2C_Rd(1);
mes = I2C_Rd(1);
anos = I2C_Rd(0); //lê o setimo byte horas e encerra as leituras de dados, graças ao sinalizador (0)
I2C_Stop();   //finaliza comunicação I2C
}


Sergio
Avatar do usuário
Sergio38br
Word
 
Mensagens: 759
Registrado em: 22 Nov 2007 13:39
Localização: São Paulo - SP

Próximo

Voltar para PIC

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

cron

x