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 CCS Technical Support

DS1307 Real Time Clock question
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Tullos
Guest







DS1307 Real Time Clock question
PostPosted: Wed Jul 14, 2004 9:26 pm     Reply with quote

This is the value I get constantly, even if I remove the crystal... I assume something is wrong if I can remove the crystal and nothing changes. Any Ideas?


25/45/-91 45:85:85
25/45/-91 45:85:85
25/45/-91 45:85:85
25/45/-91 45:85:85

Here is the code,


Code:

//=========================================
// ds1307.c -- Functions for the Dallas Semiconductor DS1307
// real time clock and NVRAM chip.
//
// The DS1307 uses BCD as its internal format, but we use it
// in binary format, outside of this module. So we have code
// to convert to/from BCD to binary in the functions below.

//----------------------------------------------------------------------
// Set the date and time.

/*
The registers inside the ds1307 are in this format. The values are in BCD.

DS1307_SECONDS_REG 0
DS1307_MINUTES_REG 1
DS1307_HOURS_REG 2
DS1307_DAY_OF_WEEK_REG 3 // We don't use this register. Set it to 0.
DS1307_DATE_REG 4
DS1307_MONTH_REG 5
DS1307_YEAR_REG 6
*/

#define DS1307_I2C_WRITE_ADDR 0xd0
#define DS1307_I2C_READ_ADDR 0xd1

// DS1307 register offsets
#define DS1307_SECONDS_REG 0
#define DS1307_MINUTES_REG 1
#define DS1307_HOURS_REG 2
#define DS1307_DAY_OF_WEEK_REG 3
#define DS1307_DATE_REG 4
#define DS1307_MONTH_REG 5
#define DS1307_YEAR_REG 6
#define DS1307_CONTROL_REG 7


#define DS1307_DATE_TIME_BYTE_COUNT 7 // Includes bytes 0-6

#define DS1307_NVRAM_START_ADDR 8

// We disable the SQWV output, because it uses
// a lot of battery current when it's enabled.
// Disable it by setting Out = Open Collector.

#define DS1307_CONTROL_REG_INIT_VALUE 0x80


char gca_ds1307_regs[DS1307_DATE_TIME_BYTE_COUNT];

void ds1307_set_date_time(void);
void ds1307_read_date_time(void);
char ds1307_read_byte(char addr);
char bcd2bin(char bcd_value);
char bin2bcd(char bin_value);
void ds1307_write_byte(char addr, char value);


void ds1307_set_date_time(void)
{
char i;
// Convert the binary ds1307 data, which is passed in a global array,
// into bcd data. Store it in the same array.

for(i = 0; i < 7; i++)
{
gca_ds1307_regs[i] = bin2bcd(gca_ds1307_regs[i]);
}

// There are two control bits embedded in the following data.
// The Clock Halt bit is in bit 7 of the DS1307 Seconds register.
// We need to make sure that it's = 0, to make the clock run.
// The other bit is the 24/12 hour clock format bit, in bit 6 of
// the DS1307 Hours register. We need 24 hour mode, so set it = 0.

gca_ds1307_regs[DS1307_SECONDS_REG] &= 0x7f;
gca_ds1307_regs[DS1307_HOURS_REG] &= 0x3f;

// Now write the 7 bytes of BCD data to the ds1307,
// using inline code for speed.
disable_interrupts(GLOBAL);

i2c_start();
i2c_write(DS1307_I2C_WRITE_ADDR);
// Start reading at the Seconds register.
i2c_write(DS1307_SECONDS_REG);

// Write 7 bytes, to registers 0 to 6.

for(i = 0; i < 7; i++)
{
i2c_write(gca_ds1307_regs[i]);
}

// After setting the time in registers 0-6, also set the
// Control register. (index = 7)

// This just turns off the squarewave output pin.
// Doing it here, every time we set the clock registers,
// seems less risky than setting it near the
// start of the program, every time the unit powers-up.
i2c_write(DS1307_CONTROL_REG_INIT_VALUE);

i2c_stop();

enable_interrupts(GLOBAL);
}

//----------------------------------------------------------------------
// Read the date and time.

// The registers inside the ds1307 are in this order.
// The values inside the registers are in BCD.

// DS1307_SECONDS_REG_ADDR 0
// DS1307_MINUTES_REG_ADDR 1
// DS1307_HOURS_REG_ADDR 2
// DS1307_DAY_OF_WEEK_REG_ADDR 3
// DS1307_DATE_REG_ADDR 4
// DS1307_MONTH_REG_ADDR 5
// DS1307_YEAR_REG_ADDR 6

// We return the data in a global array. The data in is binary.

// seconds // 0-59 seconds
// minutes // 0-59 minutes
// hours // 0-23 hours
// day_of_week // 1-7
// date // 1-31 date
// month // 1-12 month
// year // 00-99 year (based on year 2000)

void ds1307_read_date_time(void)
{
char i;
disable_interrupts(GLOBAL);

i2c_start();
i2c_write(DS1307_I2C_WRITE_ADDR);
// Start reading at the Seconds register.
i2c_write(DS1307_SECONDS_REG);

i2c_start();
i2c_write(DS1307_I2C_READ_ADDR);

// Read the 7 bytes from the ds1307. Mask off the unused bits.
gca_ds1307_regs[DS1307_SECONDS_REG] = i2c_read() & 0x7f;
gca_ds1307_regs[DS1307_MINUTES_REG] = i2c_read() & 0x7f;
gca_ds1307_regs[DS1307_HOURS_REG] = i2c_read() & 0x3f;
gca_ds1307_regs[DS1307_DAY_OF_WEEK_REG] = i2c_read() & 0x07;
gca_ds1307_regs[DS1307_DATE_REG] = i2c_read() & 0x3f;
gca_ds1307_regs[DS1307_MONTH_REG] = i2c_read() & 0x1f;
gca_ds1307_regs[DS1307_YEAR_REG] = i2c_read(0);

i2c_stop();

enable_interrupts(GLOBAL);

// Now convert the data from BCD to binary.
// Do it after reading the bytes, so that
// the i2c reads can be done quickly.

for(i = 0; i < 7; i++)
{
gca_ds1307_regs[i] = bcd2bin(gca_ds1307_regs[i]);
}

}

//------------------------------------------------------------------------
// Read one byte at the specified address.
// This function is used to access the control byte
// or the NVRAM bytes.

char ds1307_read_byte(char addr)
{
char retval;

disable_interrupts(GLOBAL);
i2c_start();
i2c_write(DS1307_I2C_WRITE_ADDR);
i2c_write(addr);

i2c_start();
i2c_write(DS1307_I2C_READ_ADDR);
retval = i2c_read(0); // Don't ACK the last byte read
i2c_stop();
enable_interrupts(GLOBAL);

return(retval);
}

//----------------------------------------------------------------------
// Write one byte to the DS1307.
// This function is used to access the control byte
// or the NVRAM bytes.

void ds1307_write_byte(char addr, char value)
{
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(DS1307_I2C_WRITE_ADDR);
i2c_write(addr);
i2c_write(value);
i2c_stop();
enable_interrupts(GLOBAL);
}
//-------------------------------------------------------------
// This function converts an 8 bit binary value
// to an 8 bit BCD value.
// The input range must be from 0 to 99.

char bin2bcd(char binary_value)
{
char temp;
char 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);
}

//--------------------------------------------------------------
// This function converts an 8 bit BCD value to
// an 8 bit binary value.
// The input range must be from 00 to 99.

char bcd2bin(char bcd_value)
{
char 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));

}




and

Code:

//test.c
///////////////////////////////////////////////////////////////////////////////
//
//
// DS1307 Driver file from PCM Programmer 18-11-03
// Version 1
//
//
////////////////////////////////////////////////////////////////////////////////

#include <16F876.h>

// If your demo board is running at 4 MHz, then change
// the HS to be XT, in the line below.

#fuses HS,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP

// If you are using a 4 MHz crystal (or 20 MHz) then change
// the value in the next line, to match your crystal frequency.
#use delay(clock=20000000)
//#use delay(clock=8000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

// My test board uses pin B7 and B6, instead of C4 and C3, so
// I've changed the #use i2c statement to reflect that, below.

#use i2c(Master, SDA=PIN_B7, SCL=PIN_B6)
//#use i2c(Master, SDA=PIN_C4, SCL=PIN_C3)

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

#include <ds1307.c>



// DS1307 register offsets
//#define DS1307_SECONDS_REG 0
//#define DS1307_MINUTES_REG 1
//#define DS1307_HOURS_REG 2
//#define DS1307_DAY_OF_WEEK_REG 3
//#define DS1307_DATE_REG 4
//#define DS1307_MONTH_REG 5
//#define DS1307_YEAR_REG 6
//#define DS1307_CONTROL_REG 7


//#define DS1307_DATE_TIME_BYTE_COUNT 7 // Includes bytes 0-6

//#define DS1307_NVRAM_START_ADDR 8

// We disable the SQWV output, because it uses
// a lot of battery current when it's enabled.
// Disable it by setting Out = Open Collector.

//#define DS1307_CONTROL_REG_INIT_VALUE 0x80

// 32.768 KHz output
//#define DS1307_CONTROL_REG_INIT_VALUE 0x13

//--------------------------------------------------------------------------
// GLOBAL VARIABLES

// This is a global array to hold data which is passed to/from the
// functions that set the ds1307 date and time.


//-----------------------------------------------------------------------
// FUNCTION PROTOTYPES

void ds1307_set_date_time(void);
void ds1307_read_date_time(void);

void ds1307_write_byte(char addr, char value);
char ds1307_read_byte(char addr);

char bin2bcd(char binary_value);
char bcd2bin(char bcd_value);

//=============================================
main()
{
char sec;
char min;
char hrs;
char day;
char date;
char month;
char yr;

printf("Start\n\r");

// Put some date and time values into the global date & time array.
gca_ds1307_regs[DS1307_SECONDS_REG] = 0; // 0 seconds
gca_ds1307_regs[DS1307_MINUTES_REG] = 10; // 10 minutes
gca_ds1307_regs[DS1307_HOURS_REG] = 8; // 8 AM
gca_ds1307_regs[DS1307_DAY_OF_WEEK_REG]= 0; // Skip this.
gca_ds1307_regs[DS1307_DATE_REG] = 19; // 19th
gca_ds1307_regs[DS1307_MONTH_REG] = 4; // April
gca_ds1307_regs[DS1307_YEAR_REG] = 02; // 2002

// Write these values to the DS1307, for testing.
ds1307_set_date_time();

// Now read the date and time once every second, and display it.
while(1)
{
delay_ms(1000);

ds1307_read_date_time();

// Get these into variables with shorter names, so I can
// put them into printf more easily.
sec = gca_ds1307_regs[DS1307_SECONDS_REG];
min = gca_ds1307_regs[DS1307_MINUTES_REG];
hrs = gca_ds1307_regs[DS1307_HOURS_REG];
day = gca_ds1307_regs[DS1307_DAY_OF_WEEK_REG];
date = gca_ds1307_regs[DS1307_DATE_REG];
month = gca_ds1307_regs[DS1307_MONTH_REG];
yr = gca_ds1307_regs[DS1307_YEAR_REG];


printf("\%d/\%d/\%02d \%d:\%d:\%02d\n\r",month,date,yr, hrs,min,sec);
}

}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jul 14, 2004 10:51 pm     Reply with quote

The first thing I have to ask, is do you have a 3v lithium battery
connected between the Vbat pin of the DS1307 and ground ?
Guest








PostPosted: Wed Jul 14, 2004 11:01 pm     Reply with quote

I ran your code as-is on a 16F876A with DS1307 on rb0, and rb1, and it worked just fine. I suspect you have a problem with your crystal or connection.
Tullos
Guest







PostPosted: Wed Jul 14, 2004 11:13 pm     Reply with quote

I connected the battery line to +5v, is that my problem?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jul 14, 2004 11:34 pm     Reply with quote

Quote:
I connected the battery line to +5v, is that my problem?

The ds1307 data sheet says the recommend minimum voltage for the
Vbat pin is 2.0v, and the maximum is 3.5v.
http://pdfserv.maxim-ic.com/en/ds/DS1307.pdf
Tullos
Guest







PostPosted: Thu Jul 15, 2004 1:10 am     Reply with quote

perfect!
cxiong



Joined: 09 Sep 2003
Posts: 52

View user's profile Send private message MSN Messenger

PostPosted: Thu Oct 21, 2004 11:00 am     Reply with quote

I use the above software for my ds1307 and I have constant display of

4/19/02 8:10:00
4/19/02 8:10:00
4/19/02 8:10:00
4/19/02 8:10:00

all the time, the time will not update at all.

Does it suppose to update the second, minute, hour etc?

I have 3.05V at Vbat.

What is wrong?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Oct 21, 2004 11:18 am     Reply with quote

Do you have a 32.768 KHz crystal across pins 1 and 2 of the DS1307 ?

Here are links to crystals that you could use:
http://rocky.digikey.com/scripts/ProductInfo.dll?Site=US&V=300&M=CFS206-32.768KDZF

http://rocky.digikey.com/scripts/ProductInfo.dll?Site=US&V=50&M=ECS-.327-12.5-13
cxiong



Joined: 09 Sep 2003
Posts: 52

View user's profile Send private message MSN Messenger

PostPosted: Thu Oct 21, 2004 11:33 am     Reply with quote

Yes,

I do have the crystal install in pin-1 and pin-2.

The crystall is:

CA-301 32.7680M-C

http://rocky.digikey.com/scripts/ProductInfo.dll?Site=US&V=114&M=CA-301%2032.7680M-C
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

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

PostPosted: Thu Oct 21, 2004 11:50 am     Reply with quote

Try enabling the square wave output and look at the signal. This will verify the clock is working.
asmallri



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

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

PostPosted: Thu Oct 21, 2004 12:01 pm     Reply with quote

I may have read the crystal spec wrong (sorry in advance if I have) but it looks to me like you have a 32MHz crystal instead of a 32KHz crystal.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Oct 21, 2004 12:05 pm     Reply with quote

It is. Look here at the Digikey catalog page.
http://dkc3.digikey.com/PDF/T043/0716.pdf
It's p/n SE3447 and it's 32.768 MHz.
That won't work.
cxiong



Joined: 09 Sep 2003
Posts: 52

View user's profile Send private message MSN Messenger

PostPosted: Thu Oct 21, 2004 12:13 pm     Reply with quote

Yes, you right.

I have a 32.768Mhz instead of 32.768Khz.


Thanks....
Guest








DS1307 Sync to PC Clock
PostPosted: Mon Jan 03, 2005 10:01 am     Reply with quote

How can I load the current time of the PC (set time clock from PC by serial) to the DS1307 instead of the following.
Code:
printf("Start\n\r");

// Put some date and time values into the global date & time array.
gca_ds1307_regs[DS1307_SECONDS_REG] = 0; // 0 seconds
gca_ds1307_regs[DS1307_MINUTES_REG] = 10; // 10 minutes
gca_ds1307_regs[DS1307_HOURS_REG] = 8; // 8 AM
gca_ds1307_regs[DS1307_DAY_OF_WEEK_REG]= 0; // Skip this.
gca_ds1307_regs[DS1307_DATE_REG] = 19; // 19th
gca_ds1307_regs[DS1307_MONTH_REG] = 4; // April
gca_ds1307_regs[DS1307_YEAR_REG] = 02; // 2002

// Write these values to the DS1307, for testing.
ds1307_set_date_time();



Please advise.

Thanks
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

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

PostPosted: Mon Jan 03, 2005 10:06 am     Reply with quote

Send the data from the PC to the PIC serially. Receive the data from the PC using the UART. Instead of using the hardcoded numbers, use the data received from the PC.

Now is that what you want to know or are you wanting someone to actually write the code for you?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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