Autor Tema: IMposible! Por que va lento el DS1307 con el 16F877  (Leído 9583 veces)

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

Desconectado venerable13

  • PIC10
  • *
  • Mensajes: 45
IMposible! Por que va lento el DS1307 con el 16F877
« en: 09 de Febrero de 2010, 19:15:24 »
Pues monto el circuito que veis a continuación



Y en la simulación va correctamente, pero al montarlo en la realidad, el reloj va muy lento, cada segundo, son 17 segundos, qué tengo mal? Además la salida de 1 HZ por el pin 7 no está y eso que la habilito.

Os paso todos los códigos empleados, mi versión de ccs compiler pcwh es la 4.088, ya que con la 4.104 he tenido algunos errores que pone que sobrepasa la memoria y con la otra versión más antigua no.

CÓDIGO FUENTE PRINCIPAL

Código: [Seleccionar]
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////ESTE PROGRAMA UTILZA EL CIRCUITO DS1307 PARA MOSTRAR LA //////////////
//////////HORA EN TIEMPO REAL A TRAVEZ DE UN UNA LCD DE 2 POR 16 CARACTERES/////
///////////////////////////////////////////////////////////////////////////////////////////////////
#include <16F877A.h>                ///   libreria para el manejo del pic16f877a
#use delay(clock=12000000)          ///   declara  la frecuencia del cristal
#fuses HS,NOWDT,NOPUT,NOLVP,NOBROWNOUT,NOWRT,NOPROTECT
#include <flex_lcd.c>
#include "_ds1307.c"
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)                     ///   con esta instruccion evitamos que
#use fast_io(D)                     ///   se este configurando cada vez que usamos
#use fast_io(E)                     ///   alguna instruccion de entrada o salida
#byte portc = 7                     /// se definen direcciones de memoria
#byte portd = 8

int sec;
int min;
int hour;
int  day;
int  mth;
int  year;
int  dow;

///////////////////////////////////////////////////////////////////////////////////
//////////////////////Comienzo de la funcion principal//////////////////////////
///////////////////////////////////////////////////////////////////////////////////
void main(){
   ds1307_init(DS1307_OUT_ENABLED | DS1307_OUT_1_HZ);
   
   set_tris_a (0x00) ;
   set_tris_d (0x00) ;
   set_tris_b (0x00) ;
   set_tris_c (0xff) ;  //set_tris_c (0x04) ;
   set_tris_e (0x00) ;
   
   lcd_init ();        /// inicializamos lcd
   // Set date FOR - > 15 June 2005 Tuesday
   // Set time FOR - > 15:20:55 (9:49:00 am)
   ds1307_set_date_time (8, 11, 7, 2, 9, 49, 00); /// se escribe en el displositivo
   /// el tiempo deseado
   WHILE (1){
      delay_ms (100) ;
      ds1307_get_date (day, mth, year, dow);  /// se obtiene la fecha
      ds1307_get_time (hour, min, sec);   /// se obtiene la hora
      lcd_gotoxy (1, 2) ;
      printf (lcd_putc, " %02d: %02d: %02d  ", hour,min,sec); ///se despliegan los datos
      lcd_gotoxy (1, 1) ;
      lcd

LIBRERÍA LCD

Código: [Seleccionar]
// flex_lcd.c

// These pins are for the Microchip PicDem2-Plus board,
// which is what I used to test the driver.  Change these
// pins to fit your own board.

#define LCD_DB4   PIN_B4
#define LCD_DB5   PIN_B5
#define LCD_DB6   PIN_B6
#define LCD_DB7   PIN_B7
//
#define LCD_RS    PIN_B1
#define LCD_RW    PIN_B2
#define LCD_E     PIN_B0

// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.

#define USE_LCD_RW   1

//========================================

#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line


int8 const LCD_INIT_STRING[4] =
{
 0x20 | (lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8 dots
 0xc,                    // Display on
 1,                      // Clear display
 6                       // Increment cursor
 };


//-------------------------------------
void lcd_send_nibble(int8 nibble)
{
// Note:  !! converts an integer expression
// to a boolean (1 or 0).
 output_bit(LCD_DB4, !!(nibble & 1));
 output_bit(LCD_DB5, !!(nibble & 2));
 output_bit(LCD_DB6, !!(nibble & 4));
 output_bit(LCD_DB7, !!(nibble & 8));

 delay_cycles(1);
 output_high(LCD_E);
 delay_us(2);
 output_low(LCD_E);
}

//-----------------------------------
// This sub-routine is only called by lcd_read_byte().
// It's not a stand-alone routine.  For example, the
// R/W signal is set high by lcd_read_byte() before
// this routine is called.

#ifdef USE_LCD_RW
int8 lcd_read_nibble(void)
{
int8 retval;
// Create bit variables so that we can easily set
// individual bits in the retval variable.
#bit retval_0 = retval.0
#bit retval_1 = retval.1
#bit retval_2 = retval.2
#bit retval_3 = retval.3

retval = 0;

output_high(LCD_E);
delay_cycles(1);

retval_0 = input(LCD_DB4);
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);

output_low(LCD_E);

return(retval);
}
#endif

//---------------------------------------
// Read a byte from the LCD and return it.

#ifdef USE_LCD_RW
int8 lcd_read_byte(void)
{
int8 low;
int8 high;

output_high(LCD_RW);
delay_cycles(1);

high = lcd_read_nibble();

low = lcd_read_nibble();

return( (high<<4) | low);
}
#endif

//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(int8 address, int8 n)
{
output_low(LCD_RS);

#ifdef USE_LCD_RW
while(bit_test(lcd_read_byte(),7)) ;
#else
delay_us(60);
#endif

if(address)
   output_high(LCD_RS);
else
   output_low(LCD_RS);

 delay_cycles(1);

#ifdef USE_LCD_RW
output_low(LCD_RW);
delay_cycles(1);
#endif

output_low(LCD_E);

lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}

//----------------------------
void lcd_init(void)
{
int8 i;

output_low(LCD_RS);

#ifdef USE_LCD_RW
output_low(LCD_RW);
#endif

output_low(LCD_E);

delay_ms(15);

for(i=0 ;i < 3; i++)
   {
    lcd_send_nibble(0x03);
    delay_ms(5);
   }

lcd_send_nibble(0x02);

for(i=0; i < sizeof(LCD_INIT_STRING); i++)
   {
    lcd_send_byte(0, LCD_INIT_STRING[i]);

    // If the R/W signal is not used, then
    // the busy bit can't be polled.  One of
    // the init commands takes longer than
    // the hard-coded delay of 60 us, so in
    // that case, lets just do a 5 ms delay
    // after all four of them.
    #ifndef USE_LCD_RW
    delay_ms(5);
    #endif
   }

}

//----------------------------

void lcd_gotoxy(int8 x, int8 y)
{
int8 address;

if(y != 1)
   address = lcd_line_two;
else
   address=0;

address += x-1;
lcd_send_byte(0, 0x80 | address);
}

//-----------------------------
void lcd_putc(char c)
{
 switch(c)
   {
    case '\f':
      lcd_send_byte(0,1);
      delay_ms(2);
      break;

    case '\n':
       lcd_gotoxy(1,2);
       break;

    case '\b':
       lcd_send_byte(0,0x10);
       break;

    default:
       lcd_send_byte(1,c);
       break;
   }
}

//------------------------------
#ifdef USE_LCD_RW
char lcd_getc(int8 x, int8 y)
{
char value;

lcd_gotoxy(x,y);

// Wait until busy flag is low.
while(bit_test(lcd_read_byte(),7));

output_high(LCD_RS);
value = lcd_read_byte();
output_low(lcd_RS);

return(value);
}
#endif

void lcd_setcursor_vb(short visible, short blink) {
  lcd_send_byte(0, 0xC|(visible<<1)|blink);
}


LIBRERÍA DS1307

Código: [Seleccionar]
///////////////////////////////////////////////////////////////////////////////////////
///                               DS1307.C                                           ///
///                     Driver for Real Time Clock                                   ///
///                     modified by Redpic 08/2006                                   ///
///                  http://picmania.garcia-cuervo.com                               ///
///                                                                                  ///
/// void ds1307_init(val)                                                            ///
///                  - Enable oscillator without clearing the seconds register       ///
///                    used when PIC loses power and DS1307 run from 3V BAT          ///
///                  - Config Control Register with next parameters:                 ///
///                     DS1307_ALL_DISABLED          All disabled                    ///
///                     DS1307_OUT_ON_DISABLED_HIHG  Out to Hight on Disable Out     ///
///                     DS1307_OUT_ENABLED           Out Enabled                     ///
///                     DS1307_OUT_1_HZ              Freq. Out to 1 Hz               ///
///                     DS1307_OUT_4_KHZ             Freq. Out to 4.096 Khz          ///
///                     DS1307_OUT_8_KHZ             Freq. Out to 8.192 Khz          ///
///                     DS1307_OUT_32_KHZ            Freq. Out to 32.768 Khz         ///
///                                                                                  ///
///                     Example init:                                                ///
///                     ds1307_init(DS1307_ALL_DISABLED);                            ///
///                     ds1307_init(DS1307_OUT_ENABLED | DS1307_OUT_1_HZ);           ///
///                                                                                  ///
/// void ds1307_set_date_time(day,mth,year,dow,hour,min,sec) - Set the date/time     ///
///                                                                                  ///
/// void ds1307_get_date(day,mth,year,dow)                   - Get the date          ///
///                                                                                  ///
/// void ds1307_get_time(hr,min,sec)                         - Get the time          ///
///                                                                                  ///
/// char ds1307_read_nvram_byte(char addr)                   - Read byte in address  ///
///                                                                                  ///
/// void ds1307_write_nvram_byte(char addr, char value)      - Write byte in address ///
///                                                                                  ///
/// void ds1307_get_day_of_week(char* ptr)                   - Get string Day Of Week///
///                                                                                  ///
/// If defined USE_INTERRUPTS all functions disable Global Interrupts on starts and  ///
///                           enable Global on ends else usar can do it hiself       ///
///                                                                                  ///
///////////////////////////////////////////////////////////////////////////////////////

#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_ENABLED          0b00010000 // Out Enabled
#define DS1307_OUT_1_HZ             0b00000000 // Freq. Out to 1 Hz
#define DS1307_OUT_4_KHZ            0b00000001 // Freq. Out to 4.096 Khz
#define DS1307_OUT_8_KHZ            0b00000010 // Freq. Out to 8.192 Khz
#define DS1307_OUT_32_KHZ           0b00000011 // Freq. Out to 32.768 Khz

#define Start_user_address_nvram    0x08
#define End_user_address_nvram      0x3f

char days_of_week[7][11]={"Lunes\0","Martes\0","Miércoles\0","Jueves\0","Viernes\0","Sábado\0","Domingo\0"};

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

void ds1307_init(int val){

   byte seconds = 0;

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

   i2c_start();
   i2c_write(0xD0);
   i2c_write(0x00);
   i2c_start();
   i2c_write(0xD1);
   seconds = ds1307_bcd2bin(i2c_read(0));
   i2c_stop();
   seconds &= 0x7F;

   delay_us(3);

   i2c_start();
   i2c_write(0xD0);
   i2c_write(0x00);
   i2c_write(ds1307_bin2bcd(seconds));
   i2c_start();
   i2c_write(0xD0);
   i2c_write(0x07);
   i2c_write(val);
   i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

void ds1307_set_date_time(byte day, byte mth, byte year, byte dow, 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_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]);
}

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

byte ds1307_bin2bcd(byte binary_value){

  byte temp;
  byte retval;

  temp = binary_value;
  retval = 0;
  while(1){
    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));
}

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

Les adjunto el programa

http://www.megaupload.com/?d=PCDAZJS9


MUCHAS GRÁCIAS, estamos mi profesor y yo mirando por qué puede ser, hay otra persona que postea que cada segundo son 40 segundos (para mi 17) pero no puso si solucionó el tema. Espero que me ayuden y grácias, como ven el código es muy sencillo pero asombrosamente no va.

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: IMposible! Por que va lento el DS1307 con el 16F877
« Respuesta #1 en: 09 de Febrero de 2010, 20:24:10 »
... pero al montarlo en la realidad, el reloj va muy lento...

¿y como es el montaje? el cristal del chip-calendario es crucial, si le entra ruido o no oscila correctamente, ten las seguridad que fallará la precisión.

La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado jeremylf

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1341
Re: IMposible! Por que va lento el DS1307 con el 16F877
« Respuesta #2 en: 09 de Febrero de 2010, 20:30:40 »
Pues lo mismo, prueba poniendo tierra en la carcasa del cristal ya sea a pulso o soldando. Con este ultimo ten cuidado no mantenerlo caliente mucho tiempo.


Salu222

Desconectado venerable13

  • PIC10
  • *
  • Mensajes: 45
Re: IMposible! Por que va lento el DS1307 con el 16F877
« Respuesta #3 en: 09 de Febrero de 2010, 20:48:23 »
tienes el diseño al principio del post, además si pongo las sondas del osciloscopio  en la frecuencia del reloj del ds me sale 50 hz (la de la red) y si lo pongo en la salida que debería sacar de un 1 hz no saca nada, pero es que también pasa QUE NO CUENTA, es decir si le meto ruido (el osci) en la lcd nunca se ve que cuenta, sólo si le quito el osci, pero es que si lo quito 1 segundo, son casi 20!! xdd, mortal

Desconectado venerable13

  • PIC10
  • *
  • Mensajes: 45
Re: IMposible! Por que va lento el DS1307 con el 16F877
« Respuesta #4 en: 09 de Febrero de 2010, 20:49:59 »
me estás diciendo q le lleve un cable de gnd a la carcasa del cristal???y lo suelde??? no entiendo, eso no lo he visto nunca si es lo q dices

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: IMposible! Por que va lento el DS1307 con el 16F877
« Respuesta #5 en: 09 de Febrero de 2010, 21:09:16 »
Soldar GND a los cristales es una forma de aislarlos del ruido. En las mother de PC suelen estar soldados a GND. También en algunos TVs.

Nunca trabajé con esos clocks ¿el cristal es el cilíndrico como el de los relojes? Si es así, la carga del osciloscopio es muy grande y te "mata" la oscilación.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado venerable13

  • PIC10
  • *
  • Mensajes: 45
Re: IMposible! Por que va lento el DS1307 con el 16F877
« Respuesta #6 en: 09 de Febrero de 2010, 21:10:15 »
#use i2c(master, sda=RTC_SDA, scl=RTC_SCL)

AHI no habría q poner SLOW??

Y AQUÍ no habría que poner standard??

#use fast_io(A)
#use fast_io(B)
#use fast_io(C)                     ///   con esta instruccion evitamos que
#use fast_io(D)                     ///   se este configurando cada vez que usamos
#use fast_io(E)                     ///   alguna instruccion de entrada o salida

leí en un post que i2c no funciona en fast, es aquí donde puede estar el error?

Desconectado venerable13

  • PIC10
  • *
  • Mensajes: 45
Re: IMposible! Por que va lento el DS1307 con el 16F877
« Respuesta #7 en: 09 de Febrero de 2010, 21:11:49 »
sois los mejores, entonces sueldo el cristal a gnd y le cambio lo que he dicho anteriormente? es decir:

pongo los puertos a standard y la librería del ds la defino como slow y pruebo a ver si funciona así?? no puede ser otra cosa que eso?

Desconectado flacoclau

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1692
    • El Micro Reactor
Re: IMposible! Por que va lento el DS1307 con el 16F877
« Respuesta #8 en: 09 de Febrero de 2010, 23:07:41 »
Amigo el cristal del ds1307 no lleva los capacitores a masa, los mismos están bajando la frecuencia de resonancia del oscilador.

En ESTE MENSAJE ya se trató el tema...
"el circuito no necesita capacitores adicionales, el mismo cristal estándar posee una capacidad inherente a su encapsulado."

Lo de la conexión a masa del cristal es muy recomendable mientras no lo recalientes con el soldador, como te dijeron los compañeros.

Saludos!!
Las personas con buena ortografía me atraen textualmente.

El Micro Reactor

Córdoba capital - Argentina.

Desconectado jeremylf

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1341
Re: IMposible! Por que va lento el DS1307 con el 16F877
« Respuesta #9 en: 10 de Febrero de 2010, 00:04:28 »
Vaya esq ni vi tu circuito por el echo de que esa echo en proteus... buneo, como dice flacoclau el ds1307 ya tiene sus propios condensadores en esas lineas, no es necesario que pongas otros externamente en la realidad.. en proteus t funciona cualuier cosa. Tambien, no olvides colocarle su condesnador de 104 en vcc y gnd tanto para el rtc como para el pic.

suerte.

Desconectado flacoclau

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1692
    • El Micro Reactor
Re: IMposible! Por que va lento el DS1307 con el 16F877
« Respuesta #10 en: 10 de Febrero de 2010, 01:14:53 »
Hola Jeremy: el chip no tiene esos capacitores, en realidad es la capacidad parásita del cristal, si es que se le puede llamar así.
Las personas con buena ortografía me atraen textualmente.

El Micro Reactor

Córdoba capital - Argentina.

Desconectado venerable13

  • PIC10
  • *
  • Mensajes: 45
Re: IMposible! Por que va lento el DS1307 con el 16F877
« Respuesta #11 en: 10 de Febrero de 2010, 08:58:21 »
cuando os puse el tema, los condensadores de 15pF también los quité y le puse un capacitor de 100nF entre la alimentación, lo único que aún no he probado es el cristal a masa, pero:

la programación está bien? aún no me han contestado conforme a las 2 preguntas que hice. Sólo me están diciendo cosas sobre el hardware, eso es que sí?

grácias

Desconectado Diego E.

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1086
Re: IMposible! Por que va lento el DS1307 con el 16F877
« Respuesta #12 en: 10 de Febrero de 2010, 09:25:06 »
Hola Venerable, la verdad todos queremos colaborarte pero por favor no te desesperes, prueba este ejemplo:

Desconectado venerable13

  • PIC10
  • *
  • Mensajes: 45
Re: IMposible! Por que va lento el DS1307 con el 16F877
« Respuesta #13 en: 10 de Febrero de 2010, 09:40:31 »
grácias, pero ahora este me va muy lento en la simulación, no se si probarlo en la vida real, xd, 1 segundo son 7 en el proteus

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: IMposible! Por que va lento el DS1307 con el 16F877
« Respuesta #14 en: 10 de Febrero de 2010, 10:08:45 »
Yo pensé que ya habías hecho la prueba....  Tiene lógica que no funcione en Fast_io, ya que para que exista un "1" en las líneas SDA y SCL dichos pines tienen que estar en alta impedancia (entrada) y si las rutinas de I2C no manejan explícitamente los TRIS (sino que se lo dejan al compilador) entonces va a haber fallas porque si se configura un puerto en Fast_io el compilador ya no toca los TRIS de dichos puertos en forma automática.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas


 

anything