I2C para RTC ds1307 (Hi-Tech C18)

Hola gente, como andan? Bueno les cuento que estoy intentando acoplar este RTC a un pic 18f452 para mostrar la hora en un lcd. El problema es que no termino de entender bien la rutina I2C que tiene mi compilador de ejemplo. Dcho sea de paso, es Hi-Tech C18.

El RTC ds1307 almacena los segundos, minutos, horas, dias, etc...cada uno en un registro de 8 bits. Cuando comienzo con la lectura, el RTC envia el primer dato (los segundos) y por cada lectura que haga, envia el proximo registro. Hasta ahi todo bien.

El problema es que no se como hacer para posicionar el registro de direccion. Cuando lo escribo por primera ves, funciona todo correcto. Se posiciona donde yo quiero. Pero despuesto cuando hago un i2c_stop() y comienzo a leer de vuelta, el registro de direccion quedo situado en el ultimo byte usado.

Existe alguna forma de volver este registro a 0, osea la primer direccion en memoria, sin tener que leer toda la memoria del RTC?
 
Última edición:
hola...yo tambien estoy en eso pero con un pic16 esta es la rutina que uso para eso esta hecha en mikroc, supongo que lo estas haciendo en picc y es casi lo mismo...es mas te lo dejo explicado para el picc....
1. tienes que enviarle un start
2. si vas a escribir los datos de la fehca, le envias la direccion 0:LOL:0(ese es elcodigo para escribir en el ds1307)
3. le envias la direccion 0
4. luego los datos....
5. el stop...
ahora yo hice una rutina que escribe es la siguiente...
despues esta la explicacion
void inicial(unsigned short add,unsigned short dato)
{
i2c_start();
i2c_write(0:LOL:0);
i2c_write(add);
i2c_write(dato);
i2c_stop();
}
bueno esta es una funcion sencilla, el add es la direcion en la que quieras escribir ya sea en los segundos, minu, hora, dia, y todo lo demas. y el dato es simplemente el dato
para llamarla lo haces de la sig forma inicial(2, 0x23) esto es add=2 (hora) dato =0x23 es decir 23 horas
para leer....la funcion es
unsigned short tiempo(unsigned short add)
{
i2c_start();
i2c_write(0:LOL:0);
i2c_write(add);
i2c_start();
i2c_write(0:LOL:1);
dato=i2c_read();
i2c_stop();
return (dato);
}
la variable add es la misma funcion de la de escritura y para llamarla es asi...
minuto=tiempo(1);
hora=tiempo(2);
año=tiempo(6);

espero que eso te sirva jeje.....pero tengo un problema.....no tiene nada que ver con la respuesta que te acabo de dar... es que el ds no me funciona cuando lo monto en fisico por que simulado en el proteus si me funciona y en fisico no....cambie el ds pero no es eso...el que pueda me podria decir que componentes externos se necesita......el cristal va con condensadores? o no es necesario.....no se...:rolleyes:

jajajajaja......disculpenme....ya resolvi mi problema....era el cable de 5v del ds1307 que estaba partido por la mitad......jeje como rayos se parte un cable de 1 cm por la mita si no lo doblo jajajajajajaja si no se me da por usar el multimetro hubiera comprado protoboard, pic, ds y hasta fuente...jejejeje
 
Última edición:
elegaba muchas gracias por responder, aunque tarde, por que a las fuerzas entendi como hacer la rutina, pero de todas formas miuchas gracias. Con lo que estoy teniendo problemas ahora es con mostrar los datos por el lcd. Vos de que forma lo estas haciendo?
saludos
 
mmm...jeje me demoro en responder por que no me queda tiempo para entrar al foro y mirar jeje pero bueno
espero que aun te sirva hay va....
cada vez que llamo la funcion de leer bueno...eso lo almaceno en una variable ya sea segundos, minutos......años en fin....y cree un vector que se llama tiempo[11]...en la posicion 0 le asigno los segundos y asi en todas luego un lcd_out(fila,columna,tiempo) hay se muestrab en la lcd digamos que de la siguiente forma 00:00:00 y lo mismo con la fecha para que salga algo asi..01/01/2010....
pero claro cuando recibes los datos del ds...entran en formato bcd y pss hay que pasar unidades y decenas de cada...variable....la forma es muy sencilla..
para las decenas seria mmmmejor hay va, por ejemplo tomas las horas corres hacia la iz4 4 bits y le sumas mm un '0', y para las unidades tomas las mismas horas y la multiplicas por 15 o 0x0f y a eso le sumas el ´0´.......si algo no queda claro me dices en sta semana estoy disponible asi que podria entrar al foro seguido...bueno espero que no sea muy tarde para la respuesta o si lo es..pss que te ayude en algo eso o....ya que jaja
en este momento estoy haciendo una lcd i2c con una lcd normal de 2x16 y un pic de 18 pines...haber como me va...bueno entoces estamos hablando:D:D:D:D:D:D
 
Hola elegaba muchas gracias por responder. Te cuento que ya no tengo problemas para enviar los datos a la pantalla. Lo resolvi tmb como utilizando un vector. Lo que me interesaria saber es si estas utilizando alguna rutina de convercion BCD a decimal y decimal a BCD para recibir y programar el ds1307 de manera correcta, o simplemente le escribes los datos en BCD.
Si puedes poner ese pedaso de tu codigo, me resolverias muchas dudas.
Saludos y muchas gracias.
 
si utilizo 2 funciones para las decenas y las unidades.....
void decenas(unsigned short dato)
{
return ((dato >> 4)+0x30);
}
void unidades(unsigned short dato)
{
return ((dato & 0x0F)+0x30);
}
no creo que halla algo que explicar de esta...como puedes ver es sencilla...
psss obviamente cuando la llames es as..
mmm.....unidades(segundos);
decenas(segundos);
y cada cosa la guardas en alguna posicion del vector que le corresponda a los segundos y a los demas.....:cool:
 
elegaba como andas? estube analisando tu respuesta, y no me parece que esta sea una rutina de convercion decimal a bcd. Si lo es, entonces no comprendo su funcionamiento
Saludos
 
Hola compañero Gonzalonal.

la rutina que te muestra el compañero elegaba no convierte de decimal a BCD mas bien convierte de BCD a ASCII para que el dato resultante lo envies directo al LCD.

Yo tambien me encuentro haciendo una rutina con este dispositivo; consiste en una alarma semanal, pero tengo problemas con el mismo ya que no consigo que retenga la fecha correctamente. Cada vez que le quito la energia pierde la fecha; la hora, minutos, segundos, mes y año lo guarda bien pero el dia del mes y el dia de la semana no me los retiene y siempre me envia el mismo dato.

Ejemplo:

almaceno la fecha 01 de Enero del 2010 con el dia de la semana en Viernes a las 00:00:00
desconecto la energia y al cabo de un minuto obtengo

10 de Enero del 2010 dia Sabado a las 00:01:00

y asi con cualquier fecha, siempre me mantiene el dia 10 y el dia de la semana en Sabado sin importar la hora o fecha que le introduzca.

Me gustaria que me compartieran su experiencia con este dispositivo. Si es error de inicializacion o que sucede por que no encuentro el error en el programa. Por cierto yo estoy usando CCS.

Saludos
 
Que tal compañeros,

pues me toco responderme a mi mismo. En efecto el problema era un problema de inicializacion, la rutina que encontre en otro foro y propiedad de redpic realiza una inicializacion leyendo los segundos del circuito para luego hacer la inicializacion. Pero el problema es que al escribir la inicializacion en el registro 0 que es de los segundos y el registro 7 que es el de configuracion no lo hacia de forma correcta.
Les adjunto la rutina de inicializacion con la correccion que le realice.
void ds1307_init(void)
{
BYTE seconds = 0;
#ifndef USE_INTERRUPTS
disable_interrupts(global);
#endif
i2c_start();
i2c_write(0:LOL:0); // WR to RTC
i2c_write(0x00); // REG 0
i2c_start();
i2c_write(0:LOL:1); // RD from RTC
seconds = bcd2bin(i2c_read(0)); // Read current "seconds" in DS1307
i2c_stop();
seconds &= 0x7F;

delay_us(3);

i2c_start();
i2c_write(0:LOL:0); // WR to RTC
i2c_write(0x00); // REG 0
i2c_write(bin2bcd(seconds)); // Start oscillator with current "seconds value
i2c_stop(); // aqui es donde corregi ya que la enterior rutina realizaba un restart pero
//por mas que le busque en el manual del DS1307 no encontre que esto se pudiera lograr
// asi que termine la escritura del registro 0 y prosegui con una nueva escritura apuntando //al registro 7

delay_us(3);

i2c_start();
i2c_write(0:LOL:0); // WR to RTC
i2c_write(0x07); // Control Register
i2c_write(0x80); // 0x80 Disable squarewave output pin, 0x10 Enable Squarewave 1Hz
i2c_stop();

#ifndef USE_INTERRUPTS
enable_interrupts(global);
#endif
}

saludos
 
gracias por corregirme jjfonsecaz:aplauso:...en efecto eso solo es para convertirlo y enviarlo a la lcd no mas...jeje...:eek:pss:
si quieres ver como funciona, hay en el mikroc lo ejecutas paso a paso y le colocas alguna valor a una variable y haces que entre a esa funcion hay se ve como funciona......cualquier vaina avisas
 
Hola amigos. Despues de mucho renegar con este integrado me tome el trabajo, mas molestia, q trabajo, de hacer una libreria de funciones para este integrado. Esta hecha para el compilador Hi-tech C pero con algunas leves modificaciones se puede pasar a cualquier compilado

A pesar de que todo suena lindo, no es asi. Tengo algunos problemas con el manejo de las funciones. Resulta que al enviar varios datos desordenadors, por ejemplo, primero la hora y despues lo segundos, el reloj hace lo que quiere. Al igual que si intento configurar los segundos los minutos y las horas, en ese orden tambien falla. El valor de los minutos, por alguna razon se los asigna a las horas.

Les paso el codigo, junto con un programa para que puedan hacer testeos a ver si me pueden dar una mano y le dejamos algo armadito a la comunidad que no vi nada muy prolijo sobre este integrado.
Les dejo el esquema armado en proteus.
Saludos
 

Adjuntos

  • ds1307.rar
    77 KB · Visitas: 235
Que tal compañero gonzalonal

Pues revise un poco el codigo, pero la verdad no tengo el compilador y no lo he usado, mas sin embargoo como ya heche a funcionar el circuito con CCS, lo unico que puede estar pasando a mi forma de ver es que no este funcionando bien el i2c.
La funcion de escritura que haces por mi esperiencia, deberias de hacerla con todos los datos en una sola funcion. Esto porque hasta en el mismo manual comenta que si haces una escritura con datos erroneos puede resultar en operaciones inesperadas.

asi que en lugar de hacer una escritura una por una te recomiendo que hagas una funcion cuyo prototipo sea como la siguiente:
void rtc_progmin(char s,char m,char h,char dds,char dia,char mes,char anyo)
{
i2c_Start();
i2c_WriteTo(0:LOL:0);
i2c_PutByte(0x00);
i2c_PutByte(dec2bcd(s));
i2c_PutByte(dec2bcd(m));
i2c_PutByte(dec2bcd(h));
i2c_PutByte(dec2bcd(dds));
i2c_PutByte(dec2bcd(dia));
i2c_PutByte(dec2bcd(mes));
i2c_PutByte(dec2bcd(anyo));
i2c_Stop();
}

disculpa si no te puedo ayudar mas, pero como te comente no tengo ese compilador.

saludos
 
muchas gracias jjfonsecaz, ya lo pude solucionar para que trabaje de la manera que quiero. No es una solucion prolija por asi decirlo, si no mas bien un parche. Despues si a alguien le interesa se las subo. Saludos y muchas gracias
 
Muchachos disculpen la demora, aca les subo mi biblioteca del ds1307.
Existen muchas rutinas para programar cada byte del ds1307. Tener en cuenta que existen rutinas mas generales como rtc_proghora y rtc_progfecha que permiten programar directamente todos los datos de la fecha y todos los datos de la hora llamando a una sola funcion.
Despues existen funciones mas particulares como las que programan los segundos, minutos, dia, año, etc pero todo por separado, es decir, programo solo los segundos, o los años o ....

Si estas rutinas mas pequeñas quieren ser utilizadas por si solas y no como parte de las funciones mas generales, se debera descomentar las lineas que tienen comentadas ya que, o bien existe un error en la rutina de instrucciones del I2C que provee Hi-Tech, o hay algun error con proteus y el protocolo o el mismo integrado. Este error ya ni me acuerdo cual era, pero creo que tenia algo que ver con que el integrado no roconocia correctamente el comando de stop a menos que se haga una lectura previa o algo asi. Ya lo veran en el codigo mismo. Me parece que es un error de proteus, no me acuerdo de haberlo probado fisicamente para comprobarlo, pero asi tal cual se los mando funciona bien el la vida real.
Espero que les sea de utilidad, cualquier cosa me avisas. Un gusto poder ayudarlos.
Saludos a todos.
 

Adjuntos

  • ds1307.rar
    2.4 KB · Visitas: 112
Atrás
Arriba