Autor Tema: Implementar NVRAM del DS1307 de Dallas  (Leído 3749 veces)

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado venerable13

  • PIC10
  • *
  • Mensajes: 45
Implementar NVRAM del DS1307 de Dallas
« en: 22 de Marzo de 2010, 22:06:40 »
Hola he estado leyendo en el foro y no encuentro la explicación exacta a mi pregunta, debido a que acabo de empezar con el ccs, cómo hago que:

-Grabar dos números en la NVRAM del DS1307

-Leer esos dos números

Lo único que se me ocurre es esto:

Añadir estas dos funciones a mi librería:

PARA LA LECTURA

Código: [Seleccionar]
char ds1307_read_nvram_byte(char addr){

   char retval;

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

   i2c_start();
   i2c_write(0xD0);
   i2c_write(addr);

   i2c_start();
   i2c_write(0xD1);
   retval = i2c_read(0);
   i2c_stop();

   return(retval);

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

PARA LA ESCRITURA

Código: [Seleccionar]
void ds1307_write_nvram_byte(char addr, char value){

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

   i2c_start();
   i2c_write(0xD0);
   i2c_write(addr);
   i2c_write(value);
   i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

Y ahora si quiero leer algo

ds1307_read_nvram_byte(0x08);

Pero donde me devuelve lo que lee? en retval?

Y si quiero escribir algo

ds1307_write_nvram_byte(0x08,min);

No será que tengo que DEFINIR una dirección de memoria y ponerlo así?

#define Memoria_minutos    0x08


ds1307_write_nvram_byte(Memoria_minutos,min);

Y para la lectura...

ds1307_read_nvram_byte(min);

Y sigo sin saber donde me devuelve lo que lee porque dependiendo lo que sea tiene que hacer una cosa u otra, por tanto, decirme por favor como leo y donde devuelve la lectura para según la que sea luego yo hacer una cosa u otra, y como escribo en la nvram.

Ah y ya que leo un número también leer dos, es decir uno lo lee y donde lo deja y otro lo lee y donde lo deja.

Como ven seguro que es muy fácil pero como acabo de empezar DIDACTICAMENTE en muchas cosas me pierdo y necesito su ayuda. Buenos muchas grácias de todas formas y se lo agradeceré mil veces. Cuídense

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Implementar NVRAM del DS1307 de Dallas
« Respuesta #1 en: 22 de Marzo de 2010, 22:13:43 »
Es sencillo, para guardar el dato leido creas una variable:

Código: C
  1. int8 Lectura;
  2.  
  3. Lectura=ds1307_read_nvram_byte(0x08);


Entonces se leerá el valor de la dirección 0x08 y se guardará en la variable Lectura.


Ahora para escribir tenes varias formas, una es usar el define como indicas, otro es usar una variable a la cual le asignas el valor que deseas escribir y otra es directamente colocando el valor:

Código: C
  1. ds1307_write_nvram_byte(0x08,56);


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado venerable13

  • PIC10
  • *
  • Mensajes: 45
Re: Implementar NVRAM del DS1307 de Dallas
« Respuesta #2 en: 22 de Marzo de 2010, 22:43:33 »
Nunca me había respondido alguien tan rápido!!! Eres un maquina!!! A ver si he entendido bien....

Si quiero leer dos variables haré lo siguiente:

al iniciar el programa leo la última hora que grabé en el DS1307 porque le he puesto una pila de 3V en el pin3 (VBAT)

int minutos_leidos=0;
int horas_leidas=0;

minutos_leidos=ds1307_read_nvram_byte(0x08);
horas_leidas=ds1307_read_nvram_byte(0x09);

MIN Y HR VAN INCREMENTANDO y escribo sus valores en la interrupción del pic (TIMER0)

      ds1307_write_nvram_byte(0x08,min);     //estas variables son de tipo byte, min y hr, está bien puesto pues?
      ds1307_write_nvram_byte(0x09,hr);

Ahora si se va la alimentación el DS1307 conservará la hora última grabada internamente porque en cada interrupción le he escrito lo valores en su NVRAM (ya que necesito esta cosa para una circuiteria externa de contadores que encienden leds de minutos y horas)

Ahora al iniciar le programa leeré los valores que tiene en la NVRAM y los comparo con los que tiene el DS1307 (la hora real)

cuando no sean iguales lo que hago es aplicarle a los contadores impulsos hasta igualarlos y así el sistema se sincronizará, es correcto?

RESUMEN

En la interrupción grabo en la nvram cada x milisengundos

Si se va la alimentación el RTC cuenta y tiene la hora suya real y la de la NVRAM (al tener la pila de 3V conectada)

Al volver la alimentación lo primero se lee la NVRAM y se compara con la hora del RTC(la real)

Si no es la misma se aplican impulsos a la circuitería externa que no está en hora, cuando sea igual el programa seguirá su curso.

Creo que el resumen está bien claro, es así cómo debo de hacerlo a groso modo?

Muchas grácias y esto empieza a ser interesante...

Si me contestan pondré la rutina de comparación  (muy fácil para algunos pero dificil para los que empiezan como yo) para el caso de que le sirva a alguien coger el concepto para sus aplicaciones
« Última modificación: 22 de Marzo de 2010, 22:52:55 por venerable13 »

Desconectado venerable13

  • PIC10
  • *
  • Mensajes: 45
Re: Implementar NVRAM del DS1307 de Dallas
« Respuesta #3 en: 23 de Marzo de 2010, 21:45:30 »
Al final no puede hacer todo, sin embargo, se leer y escribir en nvram que no está nada mal

Grácias por la buena y pronta respuesta

Desconectado leoelectronic

  • PIC10
  • *
  • Mensajes: 29
Re: Implementar NVRAM del DS1307 de Dallas
« Respuesta #4 en: 08 de Septiembre de 2010, 00:44:02 »
hola amigo Suky  :) quiero utilizar tu forma de escribir en la nvran del ds1307 con la que ayudaste a venerable13 pero tengo un problema, cuando utilizo la funcion ds1307_write_nvram_byte(0x08,56); me guarda los datos en la direccion que quiero pero no guarda el valor que se le envia por ejemplo cuando coloco 56 guarda un numero mayor  :-/ que pueda estar pasando

ayuda soy nuevo en el foro
« Última modificación: 08 de Septiembre de 2010, 00:49:41 por leoelectronic »

Desconectado mariano_pic

  • PIC18
  • ****
  • Mensajes: 498
    • Software Electronica Microncontroladores
Re: Implementar NVRAM del DS1307 de Dallas
« Respuesta #5 en: 08 de Septiembre de 2010, 15:39:13 »
Si la Vram no es la misma ram de configuracion, entonces se trata de la Sram  :D entonces no deberia de dar ningun problema, en ese caso debe haber algun error en el codigo.
Saludos.

« Última modificación: 08 de Septiembre de 2010, 16:11:56 por mariano_pic »
Necesitas ayuda para tu proyecto electronico?
buscame, tal ves pueda colaborarte.
Blog: http://electronicosembebidos.blogspot.com.co/
mail: electronicosembebidos@gmail.com
Mi grupo de facebook: https://www.facebook.com/groups/ProgramandoPics/

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Implementar NVRAM del DS1307 de Dallas
« Respuesta #6 en: 08 de Septiembre de 2010, 15:44:16 »
hola amigo Suky  :) quiero utilizar tu forma de escribir en la nvran del ds1307 con la que ayudaste a venerable13 pero tengo un problema, cuando utilizo la funcion ds1307_write_nvram_byte(0x08,56); me guarda los datos en la direccion que quiero pero no guarda el valor que se le envia por ejemplo cuando coloco 56 guarda un numero mayor  :-/ que pueda estar pasando

ayuda soy nuevo en el foro

Que extraño  :? Realiza un debug por ejemplo en Proteus para ver que dato se transmite. Si envías 56, que numero se guarda?

Hola, debes tener en cuenta antes que nada los datos a enviar al DS1307

A que te refieres, si se trata de la VRAM ?



Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado leoelectronic

  • PIC10
  • *
  • Mensajes: 29
Re: Implementar NVRAM del DS1307 de Dallas
« Respuesta #7 en: 09 de Septiembre de 2010, 01:05:19 »
bueno me explico mejor lo que quiero hacer:
primero quiero realizar la practica de RTC implementando el DS1307 con un pic 16f876 (el detalle es que estoy empezando a estudiar la comunicación i2c y programando en C con el PIC C y no se mucho solo que que he podido leer en este foro y unos libros).
bueno el detalle es como leer y escribir los datos en la memoria del DS1307, utilizando los ejemplos de este foro he podido  guardar en la dirección que quiero  :lol: es decir (en los segundos, minutos, hora, etc.........), y esas direcciones se tipean (0x00, 0x01) y cada direccion de esta escrita en un codigo :shock: ( que codigo es hex, oct, bin, dec, bcd....? no se ) y el chiste es que el dato si lo escribo con la función ds1307_write_nvram_byte(0x01,56); me guarda en el espacio de memoria asignada a los minutos pero el valor en este caso lo guarda como 36, la unica forma de escribir es colocando la funcion asi: ds1307_write_nvram_byte(0x01,0x56); de esta forma me guarda los 56 minutos en el DS1307 :? pero no se como convertir  números enteros a este formato; ademas estoy simulando en proteus y otra cosa que me parece raro es que si yo creo un bucle al infinito y leo continuamente los datos del DS1307 y los muestro en un LCD en la simulacion  despues de unos minutos se torna lento el DS1307 hasta el punto en que escribe datos solo, desordenados e incorrectos, en cambio si leeo aleatoriamene los datos el DS1307 funciona normal acumula los valores de uno en uno y todo bien  :shock: que pueda estar pasando...................?? gracias por la ayuda

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Implementar NVRAM del DS1307 de Dallas
« Respuesta #8 en: 09 de Septiembre de 2010, 10:35:07 »
Aaaaa!!! Pero una cosa es escribir datos sobre la dirección 0x08 y otra en en el rango 0x00 a 0x07. Este tiene un formato y debes pasar de binario a BCD, y al leer de BCD a binario.

Por aquí hay funciones que puedes adecuar a PIC C:
http://www.todopic.com.ar/foros/index.php?topic=22707.msg180698#msg180698


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado leoelectronic

  • PIC10
  • *
  • Mensajes: 29
Re: Implementar NVRAM del DS1307 de Dallas
« Respuesta #9 en: 09 de Septiembre de 2010, 15:32:18 »
ok amigo gracias por el link buenísimo voy a intentarlo gracias saludos :P

Desconectado leoelectronic

  • PIC10
  • *
  • Mensajes: 29
Re: Implementar NVRAM del DS1307 de Dallas
« Respuesta #10 en: 15 de Diciembre de 2010, 11:37:13 »
buenas amigo aquí de nuevo ahora con otro problema en principio ya logro ver y escribir los datos en el ds1307 pero ahora es como cambiar el formato de 24 horas a 12 horas (yo sé que es con unos de los bit de la dirección que contiene la hora pero no sé cómo controlarlo), por otra parte como controlar la salida SQW/OUT (sé que es con él registro de control pero no me funciona en la práctica solo en el simulador ) de ante manos muchas gracias.


 He aquí el programa


#include <RTC_20_11_10.h>
#include <LCD.C>
#include <_ds1307.c>


int1 selec=0,cancel=0;
int menu=0,actual,funcion=0;
byte sec, min, hr, day, mes, ano, dds;
char ds[7][5]={"Dom\0","Lun\0","Mar\0","Mie\0","Jue\0","Vie\0","Sab\0"};
char sdds[5];
//               
void mostrar_datos(){
do{
   ds1307_get_day_of_week((char*) sdds);
   ds1307_get_date(day,mes,ano,dds);
   ds1307_get_time(hr,min,sec);     
   printf(lcd_putc,"\f%s  %02d/%02d/%02d\n     %02d:%02d:%02d\n",sdds,day,mes,ano,hr,min,sec);
   if(input(PIN_C6)==0){delay_ms(150);    selec=0;    cancel=0;   return; }
   delay_ms(100);
}while(TRUE);
}
//
void acumulador(){
selec=0;    cancel=0;
do{
lcd_gotoxy(12,1);
if(funcion<=5){printf(lcd_putc,":%02d",actual);    }
if(funcion==6){printf(lcd_putc,":%s",ds[actual-1]);}
if(input(PIN_C5)==0){delay_ms(150);    return;     }
if(input(PIN_C7)==0){delay_ms(150);    actual++;   }
if(input(PIN_D3)==0){delay_ms(150);    actual--;   }
if(input(PIN_C6)==0){delay_ms(150);    selec=0;    cancel=0;   return;  }
if(funcion==1){if(actual==-1){actual=59;} else if(actual==60 ){actual=0;}}
if(funcion==2){if(actual==-1){actual=23;} else if(actual==24 ){actual=0;}}
if(funcion==3){if(actual==0 ){actual=31;} else if(actual==32 ){actual=1;}}
if(funcion==4){if(actual==0 ){actual=12;} else if(actual==13 ){actual=1;}}
if(funcion==5){if(actual==-1){actual=99;} else if(actual==100){actual=0;}}
if(funcion==6){if(actual==0) {actual=7;}  else if(actual==8)  {actual=1;}}
delay_ms(100);
}while(TRUE);
}

void main()
{
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_CLOCK_DIV_2);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);   
   ds1307_init(DS1307_ALL_DISABLED);     
   lcd_init();
   lcd_putc("REAL TIME CLOCK\n");
   lcd_putc("BY LEOELECTRONIC");
   delay_ms(2000);
do{

if(input(PIN_C5)==0){delay_ms(150); selec=1;}
if(input(PIN_C7)==0){delay_ms(150); menu++;}
if(input(PIN_D3)==0){delay_ms(150); menu--;}
if(menu==0){printf(lcd_putc,"\f%cVer   Hora\n Modif Seg",126);
   if(selec==1){mostrar_datos();}}
if(menu==1){printf(lcd_putc,"\f%cModif Seg\n Modif Min",126); 
   if(selec==1){funcion=1;   ds1307_get_time(hr,min,sec);      actual=sec;    acumulador();     if(cancel==1){return;}     ds1307_set_hora(hr, min, actual);          }}
   
if(menu==2){printf(lcd_putc,"\f%cModif Min\n Modif Hor",126); 
   if(selec==1){funcion=1;   ds1307_get_time(hr,min,sec);      actual=min;    acumulador();     if(cancel==1){return;}     ds1307_set_hora(hr, actual, sec);          }}
   
if(menu==3){printf(lcd_putc,"\f%cModif Hor\n Modif Dia",126); 
   if(selec==1){funcion=2;   ds1307_get_time(hr,min,sec);      actual=hr;     acumulador();     if(cancel==1){return;}     ds1307_set_hora(actual, min, sec);         }}
   
if(menu==4){printf(lcd_putc,"\f%cModif Dia\n Modif Mes",126); 
   if(selec==1){funcion=3;   ds1307_get_date(day,mes,ano,dds); actual=day;    acumulador();     if(cancel==1){return;}     ds1307_set_fecha(actual, mes, ano, dds);   }}
   
if(menu==5){printf(lcd_putc,"\f%cModif Mes\n Modif A#0",126); 
   if(selec==1){funcion=4;   ds1307_get_date(day,mes,ano,dds); actual=mes;    acumulador();     if(cancel==1){return;}     ds1307_set_fecha(day, actual, ano, dds);   }}
   
if(menu==6){printf(lcd_putc,"\f%cModif A#o\n Modif Dia Set",126); 
   if(selec==1){funcion=5;   ds1307_get_date(day,mes,ano,dds); actual=ano;    acumulador();     if(cancel==1){return;}     ds1307_set_fecha(day, mes, actual, dds);   }}
   
if(menu==7){printf(lcd_putc,"\f%cModif Dia Set\n Ver   Hora",126);
   if(selec==1){funcion=6;   ds1307_get_date(day,mes,ano,dds); actual=dds;    acumulador();     if(cancel==1){return;}     ds1307_set_fecha(day, mes, ano, actual);   }}
if(menu==8){menu=0;}
if(menu==-1){menu=7;}
delay_ms(150);
}while(TRUE);
}


////////////////////////////////////////////////////

Y la librería _ds1307.c




#ifndef RTC_SDA
#define RTC_SDA  PIN_C4
#define RTC_SCL  PIN_C3
#endif

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

#define DS1307_ALL_DISABLED         0b00000000 // All disabled
#define DS1307_OUT_ON_DISABLED_HIHG 0b10000000 // Out to Hight on Disable Out
#define DS1307_OUT_1_HZ             0b00010000 // Freq. Out to 1 Hz
#define DS1307_OUT_4_KHZ            0b00010001 // Freq. Out to 4.096 Khz
#define DS1307_OUT_8_KHZ            0b00010010 // Freq. Out to 8.192 Khz
#define DS1307_OUT_32_KHZ           0b00010011 // Freq. Out to 32.768 Khz
#define am                          0b00000000
#define pm                          0b00100000

#define Start_user_address_nvram    0x08
#define End_user_address_nvram      0x3f

char days_of_week[7][5]={"Dom\0","Lun\0","Mar\0","Mie\0","Jue\0","Vie\0","Sab\0"};

byte ds1307_bin2bcd(byte binary_value);
byte ds1307_bin1bcd(byte binary_value);
byte ds1307_bcd2bin(byte bcd_value);

void ds1307_init(int val){

   #ifndef USE_INTERRUPTS
   disable_interrupts(global);
   #endif

   i2c_start();
   i2c_write(0xD0);
   i2c_write(0x07);
   i2c_start();
   i2c_write(0xD0);
   i2c_write(val);
   i2c_stop();
   delay_us(3);

   #ifndef USE_INTERRUPTS
   enable_interrupts(global);
   #endif
}


void ds1307_set_hora(byte hr, byte min, byte sec){

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

  sec &= 0x7F;
  hr &= 0x3F;

  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x00);
  i2c_write(ds1307_bin2bcd(sec));
  i2c_write(ds1307_bin2bcd(min));
  i2c_write(ds1307_bin2bcd(hr));
  i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

void ds1307_set_fecha(byte day, byte mth, byte year, byte dow){

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x03);
  i2c_write(ds1307_bin2bcd(dow));
  i2c_write(ds1307_bin2bcd(day));
  i2c_write(ds1307_bin2bcd(mth));
  i2c_write(ds1307_bin2bcd(year));
  i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}
////////////////////////////////////////////////////////////////////

void ds1307_get_date(byte &day, byte &mth, byte &year, byte &dow){

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x03);
  i2c_start();
  i2c_write(0xD1);
  dow  = ds1307_bcd2bin(i2c_read() & 0x7f);
  day  = ds1307_bcd2bin(i2c_read() & 0x3f);
  mth  = ds1307_bcd2bin(i2c_read() & 0x1f);
  year = ds1307_bcd2bin(i2c_read(0));
  i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

void ds1307_get_time(byte &hr, byte &min, byte &sec){

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x00);
  i2c_start();
  i2c_write(0xD1);
  sec = ds1307_bcd2bin(i2c_read() & 0x7f);
  min = ds1307_bcd2bin(i2c_read() & 0x7f);
  hr  = ds1307_bcd2bin(i2c_read(0) & 0x3f);
  i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}


char ds1307_read_nvram_byte(char addr){

   char retval;

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

   i2c_start();
   i2c_write(0xD0);
   i2c_write(addr);

   i2c_start();
   i2c_write(0xD1);
   retval = i2c_read(0);
   i2c_stop();

   return(retval);

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

void ds1307_write_nvram_byte(char addr, char value){

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

   i2c_start();
   i2c_write(0xD0);
   i2c_write(addr);
   i2c_write(value);
   i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

void ds1307_get_day_of_week(char* ptr){

   byte lday;
   byte lmonth;
   byte lyr;
   byte ldow;
   ds1307_get_date(lday,lmonth,lyr,ldow);
   sprintf(ptr,"%s",days_of_week[ldow-1]);
}

///////////////////////////////////////////////////////////////////////////////

byte ds1307_bin2bcd(byte binary_value){

  byte temp;
  byte retval;

  temp = binary_value;
  retval = 0;
  while(TRUE){
    if(temp >= 10){
      temp -= 10;
      retval += 0x10;
    }else{
      retval += temp;
      break;
    }
  }
  return(retval);
}


byte ds1307_bcd2bin(byte bcd_value){

  byte temp;

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

///////////////////////////////////////////////////////////////////////////////


 

anything