Dúvida DS1307

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Dúvida DS1307

Mensagempor gilliard » 31 Ago 2009 00:12

:D Fala pessoal !!!! :D

Galera, estou com uma duvida chatinha aqui. é o seguinte:

Eu criei um programinha para testar meu DS1307 e minha memória 24C02, e eu aprendi, que dentro do void main, eu deveria colocar um laço while, e dentro chamar as rotinas do DS1307 e da memória 24C02, mas isso esta me trazendo um problemão.

Eu queria que enquanto o relógio fosse exibido no LCD, eu pudesse sem que o relógio deixe de ser exibido no LCD, executar outras funções, mas não estou conseguindo devido ao programa ficar preso dentro do laço while, e se sair do laço while, o relógio deixa de ser exibido no LCD. Teria outra forma de fazer esse relógio funcionar, sem ser com laço while ?

Vejam:

Código: Selecionar todos
unsigned short horas,minuto,segundo;
unsigned short dia, mes, ano, dia_semana;
unsigned short var1, var2;
char *texto;

// Rotina de conversão de dados para BCD
void BCD(unsigned short lin, unsigned short col,unsigned short var) {
  var1= (var >> 4) + 0x30;     //converte o primeiro nibble em BCD e após em string
  LCD_custom_Chr(lin,col,var1);//escreve caractere no LCD
  var2= (var & 0x0F) + 0x30;   //converte o segundo nibble em BCD e após isso, em string
  LCD_custom_Chr_Cp(var2);     //escreve caractere no LCD
}

void leitura_rtc() {     //rotina de leitura do DS1307
   I2C_Start();          //inicializa comunicação i2c
   I2C_Wr(0xD0);         //end fixo para DS1307: 1101000X, onde x = 0 é para gravação
   I2C_Wr(0);            //end onde começa a programação do relógio, end dos segundos.
   I2C_Repeated_Start(); //Issue I2C signal repeated start
   I2C_Wr(0xD1);         //end fixo para DS1307: 1101000X, onde x=1 é para leitura
   segundo= I2C_Rd(1);   //lê o primeiro byte(segundos),informa que continua lendo
   minuto= I2C_Rd(1);    //lê o segundo byte(minutos)
   horas= I2C_Rd(1);     //lê o terceiro byte(horas)
   dia_semana= I2C_Rd(1);
   dia= I2C_Rd(1);
   mes= I2C_Rd(1);
   ano= I2C_Rd(0);       //lê o sétimo byte(ano),encerra as leituras de dados
   I2C_Stop();           //finaliza comunicação I2C
}

void grava_rtc(){
   I2C_Init(100000);//iniciliza I2C com frequencia de 100KHz
   I2C_Start();     //inicializa a comunicação I2c
   I2C_Wr(0xD0);    //end fixo para DS1307: 1101000X, onde x = 0 é para gravação
   I2C_Wr(0);       //end onde começa a programação do relógio, end dos segundos.
   I2C_Wr(0x04);    //inicializa com 04 segundos.
   I2C_Wr(0x12);    //inicializa com 12 minutos.
   I2C_Wr(0x09);    //inicializa com 09:00hs (formato 24 horas).
   I2C_Wr(0x03);    //inicializa com terça
   I2C_Wr(0x17);    //inicializa com dia 17
   I2C_Wr(0x04);    //inicializa com mês 04
   I2C_Wr(0x07);    //inicializa com ano 07
   I2C_Stop();      //finaliza comunicação I2C
}

void encontra_dia_semana() {
   switch (dia_semana) {
      case 01: texto= "DOMINGO"; break;  //caso dias_semana = 01 então..
      case 02: texto= "SEGUNDA"; break;  //caso dias_semana = 02 então..
      case 03: texto= "TERCA"; break;    //caso dias_semana = 03 então..
      case 04: texto= "QUARTA"; break;   //caso dias_semana = 04 então..
      case 05: texto= "QUINTA"; break;   //caso dias_semana = 05 então..
      case 06: texto= "SEXTA"; break;    //caso dias_semana = 06 então..
      default: texto= "SABADO";          //se não for nenhum desses então...
   }
}

void display_lcd() {
   lcd_custom_cmd(lcd_clear); //apaga lcd
   Lcd_Custom_Out(1,1,"(Hora)");
   BCD(1,7,horas);            //conversão da variável horas para BCD
   LCD_custom_Chr_Cp(':');    //escreve no display LCD
   BCD(1,10,minuto);          //conversão da variável minuto para BCD
   LCD_custom_Chr_Cp(':');    //escreve no display LCD
   BCD(1,13,segundo);         //conversão da variável segundo para BCD
   Lcd_Custom_Out(2,1,"(Data)");
   BCD(2,7,dia);              //conversão da variável dia para BCD
   LCD_custom_Chr_Cp('/');    //escreve no display LCD
   BCD(2,10,mes);             //conversão da variável mes para BCD
   LCD_custom_Chr_Cp('/');    //escreve no display LCD
   BCD(2,13,ano);             //conversão da variável ano para BCD
   encontra_dia_semana();
   Lcd_Custom_out(3,1,texto); //mostra dia da semana
}

void main(){
   trisd= 0;         //define portd como saida
   adcon1= 0x06;     //torna todos os pinos AD como i/o de uso geral
   Lcd_custom_Config(&PORTD,7,6,5,4,&PORTE,2,0,1);//config LCD no modo 4 bits
   Lcd_custom_Cmd(Lcd_CLEAR);                     //apaga display
   Lcd_custom_Cmd(Lcd_CURSOR_OFF);                //desliga cursor
   grava_rtc();
   while(1){
     display_lcd();  //escreve no display lcd o valor
     leitura_rtc();  //efetua leitura de segundo, minuto e horas do DS1307
     delay_ms(200);  //delay de 200 milisegundos
   }
}


Veja o laço while:

Código: Selecionar todos
while(1){
     display_lcd();  //escreve no display lcd o valor
     leitura_rtc();  //efetua leitura de segundo, minuto e horas do DS1307
     delay_ms(200);  //delay de 200 milisegundos
};


Desde já muito obrigado a todos. Toda ajuda será bem vinda[/code]
Avatar do usuário
gilliard
Byte
 
Mensagens: 121
Registrado em: 26 Ago 2008 13:32

Mensagempor verd » 31 Ago 2009 08:20

um break talvez?
verd
Byte
 
Mensagens: 262
Registrado em: 28 Ago 2008 10:15

Mensagempor gilliard » 31 Ago 2009 10:09

Galera me ajudem !!!! Deem idéias please.
Avatar do usuário
gilliard
Byte
 
Mensagens: 121
Registrado em: 26 Ago 2008 13:32

Mensagempor verd » 31 Ago 2009 10:27

Gilliard posso pegar seu tópico e seu cóidigo como embalo?

meu mikro C é demo estou querendo implementar o codigo do Gilliard com um medidor de temperatura com saida para controle, mas é grande para meu mikro C se alguem puder me dar uma força e compilar pra mim eu agradeço!

se tiver com erro não liguem sou um aprendiz!


const unsigned short TEMP_RESOLUTION = 12;
const int RES_FACTOR_1[4] = {5000, 2500, 1250, 625};
const unsigned int RES_FACTOR_2[4] = {0x0001, 0x0003, 0x0007, 0x000F};
const unsigned int RES_FACTOR_3[4] = {0x8000, 0xC000, 0xE000, 0xF000};
float alarma;
unsigned temp,temp2,new_temp;
unsigned short j, RES_SHIFT,j2;


unsigned short horas,minuto,segundo;
unsigned short dia, mes, ano, dia_semana;
unsigned short var1, var2;
char *texto;

void BCD(unsigned short lin, unsigned short col,unsigned short var) {
var1= (var >> 4) + 0x30; //converte o primeiro nibble em BCD e após em string
LCD_custom_Chr(lin,col,var1);//escreve caractere no LCD
var2= (var & 0x0F) + 0x30; //converte o segundo nibble em BCD e após isso, em string
LCD_custom_Chr_Cp(var2); //escreve caractere no LCD
}

void leitura_rtc() { //rotina de leitura do DS1307
I2C_Start(); //inicializa comunicação i2c
I2C_Wr(0xD0); //end fixo para DS1307: 1101000X, onde x = 0 é para gravação
I2C_Wr(0); //end onde começa a programação do relógio, end dos segundos.
I2C_Repeated_Start(); //Issue I2C signal repeated start
I2C_Wr(0xD1); //end fixo para DS1307: 1101000X, onde x=1 é para leitura
segundo= I2C_Rd(1); //lê o primeiro byte(segundos),informa que continua lendo
minuto= I2C_Rd(1); //lê o segundo byte(minutos)
horas= I2C_Rd(1); //lê o terceiro byte(horas)
dia_semana= I2C_Rd(1);
dia= I2C_Rd(1);
mes= I2C_Rd(1);
ano= I2C_Rd(0); //lê o sétimo byte(ano),encerra as leituras de dados
I2C_Stop(); //finaliza comunicação I2C
}

void grava_rtc(){
I2C_Init(100000);//iniciliza I2C com frequencia de 100KHz
I2C_Start(); //inicializa a comunicação I2c
I2C_Wr(0xD0); //end fixo para DS1307: 1101000X, onde x = 0 é para gravação
I2C_Wr(0); //end onde começa a programação do relógio, end dos segundos.
I2C_Wr(0x04); //inicializa com 04 segundos.
I2C_Wr(0x15); //inicializa com 12 minutos.
I2C_Wr(0x09); //inicializa com 09:00hs (formato 24 horas).
I2C_Wr(0x02); //inicializa com SEGUNDA
I2C_Wr(0x31); //inicializa com dia 31
I2C_Wr(0x08); //inicializa com mês 08
I2C_Wr(0x09); //inicializa com ano 09
I2C_Stop(); //finaliza comunicação I2C
}



void encontra_dia_semana() {
switch (dia_semana) {
case 01: texto= "DOMINGO"; break; //caso dias_semana = 01 então..
case 02: texto= "SEGUNDA"; break; //caso dias_semana = 02 então..
case 03: texto= "TERCA"; break; //caso dias_semana = 03 então..
case 04: texto= "QUARTA"; break; //caso dias_semana = 04 então..
case 05: texto= "QUINTA"; break; //caso dias_semana = 05 então..
case 06: texto= "SEXTA"; break; //caso dias_semana = 06 então..
default: texto= "SABADO"; //se não for nenhum desses então...
}
}
void display_lcd() {
lcd_custom_cmd(lcd_clear); //apaga lcd

BCD(1,9,horas); //conversão da variável horas para BCD
LCD_custom_Chr_Cp(':'); //escreve no display LCD
BCD(1,12,minuto); //conversão da variável minuto para BCD
LCD_custom_Chr_Cp(':'); //escreve no display LCD
BCD(1,15,segundo); //conversão da variável segundo para BCD

BCD(1,18,dia); //conversão da variável dia para BCD
LCD_custom_Chr_Cp('/'); //escreve no display LCD
BCD(1,21,mes); //conversão da variável mes para BCD
LCD_custom_Chr_Cp('/'); //escreve no display LCD
BCD(1,24,ano); //conversão da variável ano para BCD
encontra_dia_semana();
Lcd_Custom_out(1,1,texto); //mostra dia da semana
}

void Display_Temperature(unsigned int temp) {
const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8;
unsigned int temp_whole, temp_fraction;
unsigned short i;
char text[8];

temp_fraction = temp & RES_FACTOR_2[RES_SHIFT - 1];
temp_fraction = temp_fraction * RES_FACTOR_1[RES_SHIFT - 1];
temp_whole = temp;

if ((temp_whole & 0x8000) != 0u) i = 1; // Yes, i = 1
else i = 0; // No, i = 0

temp_whole >>= RES_SHIFT;

if (i) temp_whole |= RES_FACTOR_3[RES_SHIFT - 1];

IntToStr(temp_whole, text); // Convert whole part to string
Lcd_Out(2, 23, text); // Print whole part on LCD
Lcd_Chr_Cp('.'); // Print dot to separate fractional part

IntToStr(temp_fraction, text); // Convert fractional part to string
if (temp_fraction < 100u) Lcd_Chr_Cp('0');
if (temp_fraction < 10u) Lcd_Chr_Cp('0');

Lcd_Chr_Cp(223); // Print degree character
Lcd_Chr_Cp('C'); // Print 'C' for Centigrades
}//~

void main() {
PORTE = 0xFF;
TRISE = 0x0F; // PORTE is input
PORTB = 0;
TRISB = 0; // PORTB is output
TRISD=0;
PORTD=0;
TRISC=0;
PORTC=0;
adcon1= 0x06; //torna todos os pinos AD como i/o de uso geral
Lcd_custom_Config(&PORTD,7,6,5,4,&PORTB,2,0,1);//config LCD no modo 4 bits
Lcd_custom_Cmd(Lcd_CLEAR); //apaga display
Lcd_custom_Cmd(Lcd_CURSOR_OFF); //desliga cursor
grava_rtc();
while(1){
display_lcd(); //escreve no display lcd o valor
leitura_rtc(); //efetua leitura de segundo, minuto e horas do DS1307
delay_ms(1000); //delay de 200 milisegundos
}
Lcd_Init(&PORTB);
Lcd_Cmd(Lcd_CURSOR_OFF);
Lcd_Out(2, 1, "TEMP. EMPACOTADEIRA:");
do { // main loop

Ow_Reset(&PORTE,2); // Onewire reset signal
Ow_Write(&PORTE,2,0xCC); // Issue command SKIP_ROM
Ow_Write(&PORTE,2,0x44); // Issue command CONVERT_T
Delay_us(120);

Ow_Reset(&PORTE,2);
Ow_Write(&PORTE,2,0xCC); // Issue command SKIP_ROM
Ow_Write(&PORTE,2,0xBE); // Issue command READ_SCRATCHPAD
Delay_ms(400);

j = Ow_Read(&PORTE,2); // Get temperature LSB
j2=j;
temp = Ow_Read(&PORTE,2); // Get temperature MSB
temp2=temp;
temp <<= 8; temp += j; // Form the result
temp2<<=5;
j2>>=3;
new_temp=temp2^j2;
portd=new_temp;
// alarma=39;
alarma=((new_temp*127.5)/255);
// if(((alarma>=36.5)&&(alarma<=38))) { //YESÝL LED AKTIF

if (alarma>=36){
PORTC.F0=0;
}

else {
portc.f0=1;}
Display_Temperature(temp); // Format and display result on LCD
Delay_ms(500);
} while (1);
}//~!
verd
Byte
 
Mensagens: 262
Registrado em: 28 Ago 2008 10:15

Mensagempor ivan » 31 Ago 2009 11:27

Gilliard, como vc pediu uma sugestão, então vai:

Primeiro otimizar o código de escrita no LCD, montando o texto(HH:MM:SS) da linha em um array, já na leitura do rtc lendo os dados de uma vêz só, e depois imprimindo tb de uma vez só.
Fazer uma tabela com o texto de dias da semana, onde o acesso fosse direto por indice, acabando com a rotina "encontra_dia_semana".
Pra q tudo isso? Para ganhar velocidade e escrever no LCD, através de uma int de aprox. 1s em 1s, o + rápido possível, liberando o processador para as outras tarefas.

Funciona? Não sei! Como eu disse no início, é uma sugestão.
"A mente que se abre a uma nova idéia jamais volta ao seu tamanho original." (Albert Einstein).
Avatar do usuário
ivan
Word
 
Mensagens: 618
Registrado em: 12 Out 2006 21:27

Mensagempor gilliard » 31 Ago 2009 19:23

Não faço nem ideía de como implementar a idéia do ivan, alguem me ajuda ?!?!?
Avatar do usuário
gilliard
Byte
 
Mensagens: 121
Registrado em: 26 Ago 2008 13:32

Mensagempor gilliard » 01 Set 2009 08:13

Pessoal, me ajuedem com esse problema, com exemplos, dicas, etc... Dai eu vou fazendo, e voces mostrando o caminho, até eu resolver o problema.
Avatar do usuário
gilliard
Byte
 
Mensagens: 121
Registrado em: 26 Ago 2008 13:32

Mensagempor fabim » 01 Set 2009 08:19

gilliard escreveu:Pessoal, me ajuedem com esse problema, com exemplos, dicas, etc... Dai eu vou fazendo, e voces mostrando o caminho, até eu resolver o problema.
,

AIIIIIII aí´´iíííí

O tio, seguinte, este DS tem um pino com CK configuravel né?
Ele da um pulso de alguns mS a cada 1S né ?
Porque você não usa este CK para gerar uma interrupção em borda de subida no RB0 ? e lá dentro da interruppção, muito rapidão você le e toma as devidas providencias de tratamento ?

enquanto isso no main, você pode fazer o que bem entender..
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor gilliard » 01 Set 2009 09:34

Fala ae Fabim, tudo bem ?!?!?

Então TIO, o pino de CK já esta sendo utilizado no RB4. Qual outra sugestão vc daria ?!?!?
Avatar do usuário
gilliard
Byte
 
Mensagens: 121
Registrado em: 26 Ago 2008 13:32


Voltar para PIC

Quem está online

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

cron

x