CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

ds1307 time is automatically decreasing

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
nisha



Joined: 09 Nov 2011
Posts: 6
Location: mumbai

View user's profile Send private message Send e-mail

ds1307 time is automatically decreasing
PostPosted: Mon Oct 22, 2012 3:47 am     Reply with quote

I'm using ds1307 interfaced with pic16f877a. My code is working but the problem is, if I'm continuously keeping it on, the time goes on reducing. Say after 10 to 15 min it will decrease by 1 sec, which will create a problem after some hour or some days.
Plz help me.
_________________
Nisha Yetiwar
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Mon Oct 22, 2012 3:55 am     Reply with quote

Are you getting the time once from the DS1307 and then running an internal based clock on the PIC or reading the time from the 1307 every time?

If the former, then you have to remember that if you're not using a crystal for the PIC that evenly divides out by the timer you're using, you can end up with slippage. A smaller number than an even divider and your clock runs too fast. A larger number than the divider and your clock runs too slow.

In the case of the latter, it sounds like the clock source for the 1307 is running fast.

If I remember right, the 1307 has pins to allow measuring the 32.768KHz clock through a buffer.

You should do that. If you have a frequency counter, that's most likely a better option than a scope.

Additionally, how is this DS1307 wired? on a breadboard?

Did you read the datasheet for the DS1307 and note all the commentary about critical layout for the crystal connection? (if you're using a crystal)
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
asmallri



Joined: 12 Aug 2004
Posts: 1634
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Mon Oct 22, 2012 8:16 pm     Reply with quote

Adding to bkamen's comments,

The DS1307 requires a crystal that operates with 12pf loading. Two common mistakes when using this chip is to use the wrong crystal and the other is to add two external 12pF capacitors when this is already built into the chip. In both scenarios the frequency will be wrong.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
nisha



Joined: 09 Nov 2011
Posts: 6
Location: mumbai

View user's profile Send private message Send e-mail

PostPosted: Thu Oct 25, 2012 1:14 am     Reply with quote

i m using 32.768khz crystal, for ds1307. yes but i have not connected 12pf cap to my crystal..i searched for ckt diagram on net, there 12pf was connected. is it necessary..

And i m not using breadboard, components and wires are properly soldered

For pic16f877a, i m using 4Mhz external crystal.should i go for higher freq.
_________________
Nisha Yetiwar
asmallri



Joined: 12 Aug 2004
Posts: 1634
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Thu Oct 25, 2012 1:49 am     Reply with quote

nisha wrote:
i m using 32.768khz crystal, for ds1307. yes but i have not connected 12pf cap to my crystal..i searched for ckt diagram on net, there 12pf was connected. is it necessary..

And i m not using breadboard, components and wires are properly soldered

For pic16f877a, i m using 4Mhz external crystal.should i go for higher freq.


The capacitors are not necessary. Check the Dallas (Maxim-IC) data sheet.

Are you using the correct crystal?

Are you reading the chip correctly - not inadvertently starting and stopping the oscillator?
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
Ttelmah



Joined: 11 Mar 2010
Posts: 19447

View user's profile Send private message

PostPosted: Thu Oct 25, 2012 1:52 am     Reply with quote

OK.
First thing is forget about the 'net'. Look instead at the actual data sheet for the clock chip. Paragraph about the crystal:

"The internal oscillator circuitry is designed for operation with a crystal having a specified load capacitance (CL) of 12.5 pF".

So, what is the specified load capacitance of _your_ crystal. If it is one that requires 6pF capacitance (quite common for 32KHz crystals), then the Cl of the IC will be too high, and the circuit _will_ run slow.

Now, the reason I say 'forget about the net', is that while a huge amount of good data does get published, a lot of incorrect things also do. You see people using 12pF capacitors on crystals that require a 12pF load - wrong - the crystal sees the two capacitors in series, and paralleled to the pin/track capacitance, so even where a capacitor is needed, this gives completely the wrong load.

The crystal pins of the DS1307, are designed to already give a 12.5pF load, and provided your crystal wants this load, external capacitors are not wanted.

However careful layout is. "Carefully soldered", but to what?. The traces to the crystal need to be _short_. The chip is designed to have just a fraction of a pF of stray capacitance on the tracks. More than a few mm of track, and again the load will be more than required. You also need to avoid running (for example) a ground plane actually round the crystal legs. This again increases capacitance, and will slow the clock. What you want is a 'guard ring' round outside the pins, that is itself tied to ground, leaving an oval of bare board on the top of the board round the actual legs, and then run a ground plane under the board (bottom layer).

The frequency of the PIC doesn't really matter here.

However you do need to be aware of what overall accuracy you can expect. Watch crystals are remarkably forgiving, but are at there most accurate in reasonably temperature stable environment. Gently held at a nice body temperature on your wrist, they give better accuracies than they will with wider temperature changes. The curve as temperature changes, is parabolic, so reasonably flat for the temperatures between 20C, and perhaps 28C, but go to temperatures like 10C, and the accuracy will descend. The initial tolerance on a typical watch crystal, will be +/-20ppm, which gives an error of 1.73 seconds per day. Add temperature errors, and this can easily be three or four seconds per day, even if everything is built as it should be. Too get better than this, you have to go to actually trimming the crystal (which the DS1307 is not designed to allow), and temperature regulating. So your error is at least an order of magnitude 'worse' than it should be. The fact that it is slow, suggests there is too much capacitance (so adding capacitors is _not_ the way to go). Either the crystal you have is designed for a lower load, or your layout is adding a lot of stray capacitance.

Best Wishes
nisha



Joined: 09 Nov 2011
Posts: 6
Location: mumbai

View user's profile Send private message Send e-mail

PostPosted: Thu Oct 25, 2012 4:50 am     Reply with quote

And this is my driver file
Code:

#define RTC_SDA  PIN_C4
#define RTC_SCL  PIN_C3

#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(0x10);     // Enable 10 squarewave output pin       // disable 10000000=80
   i2c_stop();
}

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

  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(0x10);              // REG 7 - Disable squarewave output pin   //disable=80
  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(1) & 0x7f);
  min = bcd2bin(i2c_read(1) & 0x7f);
  hr  = bcd2bin(i2c_read(1) & 0x7f);       //3f
  //year = bcd2bin(i2c_read(0));
  i2c_stop();
}


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

  temp = binary_value;
  retval = 0;

  while(1)
  {
    // 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));
}

_________________
Nisha Yetiwar


Last edited by nisha on Thu Oct 25, 2012 4:51 am; edited 1 time in total
nisha



Joined: 09 Nov 2011
Posts: 6
Location: mumbai

View user's profile Send private message Send e-mail

PostPosted: Thu Oct 25, 2012 4:50 am     Reply with quote

This is my Main program, please tell me where is the mistake. I changed my crystal from 4 to 20 Mhz of PIC.
Code:

#include <16f877A.h>
#FUSES NOWDT, HS, NOPUT, PROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=20000000)

#include <ds_driver.c>

#byte porta= 0x05
#byte portb= 0x06
#byte portc= 0X07
#byte portd= 0X08
#byte porte= 0X09
#byte trisa= 0x85
#byte trisb= 0x86
#byte trisc= 0X87
#byte trisd= 0X88
#byte trise= 0X89

void clear(void);
void bin_2_bcd(int16, int16, int16, int16, int16);

int32 hour, minute, second, dat, month, year, day, time, total_disp;
int8 D1,D2,D3,D4,D5,D6,D7,D8,D9,D10,i,prog;
int8 seven_table[27]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x79,0x50,0x5c};
//                                                                              E    r    o
char  dt, mth, yr, dow, hr, min, sec;


#int_EXT
EXT_isr()
{
ds1307_get_date(dt,mth,yr,dow);
ds1307_get_time(hr,min,sec);
}

#int_TIMER2
TIMER2_isr()

   switch(i)
      {
       case 0 : output_low(PIN_E2); output_d(seven_table[D1]); output_high(PIN_B4); i=1; break;

       case 1 : output_low(PIN_B4); output_d(seven_table[D2]); output_high(PIN_B5); i=2; break;

       case 2 : output_low(PIN_B5); output_d(seven_table[D3]); output_high(PIN_C0); i=3; break;

       case 3 : output_low(PIN_C0); output_d(seven_table[D4]); output_high(PIN_C1); i=4; break;

       case 4 : output_low(PIN_C1); output_d(seven_table[D5]); output_high(PIN_C5); i=5; break;

       case 5 : output_low(PIN_C5); output_d(seven_table[D6]); output_high(PIN_C6); i=6; break;

       case 6 : output_low(PIN_C6); output_d(seven_table[D7]); output_high(PIN_C7); i=7; break;

       case 7 : output_low(PIN_C7); output_d(seven_table[D8]); output_high(PIN_E0); i=8; break;

       case 8 : output_low(PIN_E0); output_d(seven_table[D9]); output_high(PIN_E1); i=9; break;

       case 9 : output_low(PIN_E1); output_d(seven_table[D10]); output_high(PIN_E2); i=0; break;
      }
}

void main(void)

   int8 temp=0;
   delay_ms(100);
   output_low(PIN_B4); output_low(PIN_B5); output_low(PIN_C0);       output_low(PIN_C1); output_low(PIN_C5);
   output_low(PIN_C6); output_low(PIN_C7); output_low(PIN_E0); output_low(PIN_E1); output_low(PIN_E2);
   i=0; time=0;
   clear();
   ds1307_init();
   setup_timer_2(T2_DIV_BY_4,250,1); enable_interrupts(INT_TIMER2);
   enable_interrupts(INT_EXT);  enable_interrupts(GLOBAL);
ds1307_set_date_time(25,10,12,4,4,30,10); //date,mth,yr,dow,hr,min,sec

while(1)
  {
    dat=dt;month=mth;year=yr;
    hour=hr; minute=min; second=sec;
    bin_2_bcd(hour, minute, second, dat, month); //right nw i have only 10 display,that's why i m display only this much.
  }
}


void clear(void)
{
D1=0; D2=0; D3=0; D4=0; D5=0; D6=0; D7=0; D8=0; D9=0; D10=0; dt=0; mth=0; yr=0;dow=0; hr=0; min=0; sec=0;  day=0; time=0; dat=0; month=0; year=0; hour=0; minute=0; second=0;}


void bin_2_bcd(int16 hour, int16 minute, int16 second, int16 dat, int16 month)
{
 D10=month%10;
 month/=10;
 D9=month%10;

 D8=dat%10;
 dat/=10;
 D7=dat%10;

 D6=second%10;
 second/=10;
 D5=second%10;

 D4=minute%10;
 minute/=10;
 D3=minute%10;

 D2=hour%10;
 hour/=10;
 D1=hour%10;
}

_________________
Nisha Yetiwar


Last edited by nisha on Thu Oct 25, 2012 5:05 am; edited 3 times in total
nisha



Joined: 09 Nov 2011
Posts: 6
Location: mumbai

View user's profile Send private message Send e-mail

PostPosted: Thu Oct 25, 2012 4:56 am     Reply with quote

i am using square wave op of my ds whose freq is 1 hz, which is connected to the RB0 pin of my pic controller,
means i am using external interrupt, which will read data after every 1 sec..
_________________
Nisha Yetiwar
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Thu Oct 25, 2012 9:25 am     Reply with quote

nisha wrote:
i am using square wave op of my ds whose freq is 1 hz, which is connected to the RB0 pin of my pic controller,
means i am using external interrupt, which will read data after every 1 sec..



1Hz or 1.000Hz or 1.001Hz?

Decimal points matter here.

If you say (in your original post) that your clock is short 1sec after 10-15min. (we'll use 10min as a starting point) then...

599sec / 600 (which is 10min) = 0.99833

So your clock is 0.99833 Hz, not 1.0000Hz

Again - the DS1307 has a buffered CLK output to measure the crystal. Yes. It's also the OUT pin (#7) so you'll need to re-program it for a moment to measure FREQ instead of seconds.

Again, it sounds like your crystal is running fast.

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group