# Q> about DS1307 code

Status
Not open for further replies.

#### ivalex

##### Newbie level 4
I have a problem with the code that I found and modified a bit to suit the ccs c compiler

I tried printing out the hours:min:secs and what I got was -1:-1:-1

I checked before the variable secs was used in the writing sequence of the i2c and saw that it is still fine (55)

Is there something wrong with the code? I'm wondering if whats wrong is in the write sequence or the read sequence... btw, the test_ variables were going to be used to compare with the time that the ds1307 produces so that at a certain time, I will enable outputs to all ports (0xFF)

If it would help the "investigation", I have no 3v lithium battery connected to pin3 of the ds1307 since I can't get a hold of any 3v bat... Hopefully this is not the problem
Code:
#include <16F877A.h> //Initialization
#include <string.h>
#fuses HS, NOWDT, NOPROTECT, NOLVP, PUT
#use delay (clock=20000000)
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(master, sda=PIN_C4, scl=PIN_C3, FAST=100000)

unsigned short read_ds1307(unsigned short address );
void write_ds1307(unsigned short address,unsigned short w_data);
unsigned int sec;
unsigned int min;
unsigned int hrs;
unsigned int day;
unsigned int month;
unsigned int yr;
unsigned int dow;
unsigned int data;
unsigned int test_sec;
unsigned int test_minute;
unsigned int test_hour;
unsigned int test_day;
unsigned int test_date;
unsigned int test_month;
unsigned int test_year;

void write_ds1307(unsigned int day, unsigned int mth, unsigned int year, unsigned int dow, unsigned int hr, unsigned int min, unsigned int sec)
{

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

i2c_start();
i2c_write(0xD0);            // I2C write address
i2c_write(0x00);            // Start at REG 0 - Seconds
i2c_write(sec);             // REG 0
i2c_write(min);      // REG 1
i2c_write(hr);      // REG 2
i2c_write(dow);      // REG 3
i2c_write(day);      // REG 4
i2c_write(mth);      // REG 5
i2c_write(year);      // REG 6
i2c_write(0x80);            // REG 7 - Disable squarewave output pin
i2c_stop();

i2c_start();
i2c_write(0xD0); // address DS1307
i2c_write(0); // start from word at address 0
i2c_write(0); // write 0 to REG0 (enable counting + 0 sec)
i2c_stop();
}

void ds1307_get_time()
{
i2c_start();
i2c_write(0xD0);
i2c_write(0x00);            // Start at REG 0 - Seconds
i2c_start();
i2c_write(0xD1);
sec = i2c_read(1);
min = i2c_read(1);
hrs  = i2c_read(1);
dow  = i2c_read(1);
day  = i2c_read(1);
month  = i2c_read(1);
yr  = i2c_read(0);
i2c_stop();
}

void init_ds1307()
{
int seconds = 0;

i2c_start();
i2c_write(0xD0);      // WR to RTC
i2c_write(0x00);      // REG 0
i2c_start();
i2c_write(0xD1);      // RD from RTC
seconds = i2c_read(0);
i2c_stop();
seconds &= 0x7F;

delay_us(3);

i2c_start();
i2c_write(0xD0);      // WR to RTC
i2c_write(0x00);      // REG 0
i2c_write(seconds);
i2c_start();
i2c_write(0xD0);      // WR to RTC
i2c_write(0x07);      // Control Register
i2c_write(0x80);     // Disable squarewave output pin
i2c_stop();
}

void main()
{ //Start of Main Program

//set_tris_b(0x00);
set_tris_c(0x18);
Delay_ms(1000);

// Set date for -> 15 June 2005 Tuesday
// Set time for -> 15:20:55
write_ds1307(15,6,5,2,15,20,55); //day,mth,yr,dow,hr,min,sec

while(1)
{
Delay_ms(1000);
ds1307_get_time();

printf("\%02d:\%02d:\%02d\n", hrs,min,sec);

}
} //End of program

Staff member
ivalex

### ivalex

points: 2
Helpful Answer Positive Rating

#### ivalex

##### Newbie level 4
Thanks it worked, I forgot the initialization of the CH bit... got confused with the D0, thought that was the one being written on seconds

Another EDIT:

I got it to work finally, but, just a side question, what should I check/bit test to see if there is a time already placed inside the RTC

What I want to do is to prevent the MCU to overwrite the current time placed in the RTC, any suggestions prior to this problem?

Much appreciated to those who will reply :lol:

Last edited:

#### andre_teprom

##### Super Moderator
Staff member
hi ivalex,

You can check it from 2 ways :

1 ) By hardware : If the output pin of the RTC is configured to generate a clock, detecting a signal there, you can assume that the IC was already started to work.
2 ) By firmware : Just checking if time inside it is compatible to GMT-n ( where n is an integer number ). It means that a valid timezone is programmed, and not spurious data.

+++

ivalex

### ivalex

points: 2
Helpful Answer Positive Rating

#### ivalex

##### Newbie level 4
hi ivalex,

You can check it from 2 ways :

1 ) By hardware : If the output pin of the RTC is configured to generate a clock, detecting a signal there, you can assume that the IC was already started to work.

2 ) By firmware : Just checking if time inside it is compatible to GMT-n ( where n is an integer number ). It means that a valid timezone is programmed, and not spurious data.

+++
Clarify:
1.) By output pin, u mean pin7 ryt? so the configuration that I would need is to enable a 1hz that is coming out of the DS1307? so by checking it, I would have a wire connected to it and placed at something like portb(1) then check if there is an input there?

e.g.
if(portb(1) != 1)
write_ds1307

2.) sorry but I didn't quite understand what I should do with this T_T

btw, thanks for the quick reply

Last edited:

#### andre_teprom

##### Super Moderator
Staff member
ivalex,

Follows observations regarding your doubt to previous sugestions I posted :

1 ) By hardware : If the output pin of the RTC is configured to generate a clock, detecting a signal there, you can assume that the IC was already started to work.
> You got the exact concept sugested. By reading the output pin you know if DS1307 is operating.
...what should I check/bit test to see if there is a time already placed inside the RTC...
2 ) By firmware : Just checking if time inside it is compatible to GMT-n ( where n is an integer number ). It means that a valid timezone is programmed, and not spurious data.
> It must be done, assuming that the evaluation will be done while board is connected to a PC.
Take in mind that, once RTC is used at design, a communication to PC must be predicted.
...What I want to do is to prevent the MCU to overwrite the current time placed in the RTC...

ivalex

### ivalex

points: 2
Helpful Answer Positive Rating

#### ivalex

##### Newbie level 4
Thanks for the very quick repliy, well, I tried using my own method that I thought of, not sure if its optimized or encouraged to do, but basically, what I did is that I store the time in the RAM of the DS1307, then whenever the MCU starts, it will read the stored time in the DS1307 and save it to the registers inside the MCU

Code:
void main()
{ //Start of Main Program

int sec;
int min;
int hrs;
int day;
int month;
int yr;
int dow;

int test_sec = 0;
int test_minute = 0;
int test_hour = 5;
int test_day = 1;
int test_date = 4;
int test_month = 6;
int test_year = 11;

set_tris_c(0x18);
init_ds1307();

Delay_ms(1000);

/////Next 2 lines prevent overwriting the current time placed in
/////DS1307 by reading the stored time in the DS1307 itself
ds1307_read_store(sec,min,hrs,day,month,yr,dow);
write_ds1307(day,month,yr,dow,hrs,min,sec);

/*
/////For First time writing time in the DS1307
write_ds1307(3,6,11,6,11,25,10);
/////Comment line above to prevent overwriting the current time placed
*/
while(1)
{
Delay_ms(1000);

ds1307_get_time(hrs,min,sec);
ds1307_get_date(day,month,yr,dow);

if(test_sec == sec && test_minute == min && test_hour == hrs && test_day == day && test_date == dow && test_month == month && test_year == yr)
{
output_d(0xff);
}

ds1307_store_time(sec,min,hrs,day,month,yr,dow);
printf("Day:%02d, Month:%02d, Year:%02d\n",day,month,yr);
printf("\%02d:\%02d:\%02d\n", hrs,min,sec);
}
} //End of program

it worked but, I want to use the computer time to make it more accurate because the code that I pasted below is hardcoded... Whenever I update the current time in the DS1307, there are always a delay between times and whenever I open the MCU, the time being read is delayed by something like 5-10secs... so a bit off topic but can u help me to use time.h??

I keep getting the error, "Function used but not defined: ... time SCR=1944" whenever I want to use the function localtime
Code:
time_t curtime;
struct_tm *t;
curtime = time(NULL);
t=localtime(&curtime);

#### andre_teprom

##### Super Moderator
Staff member
ivalex,

I´m not sure if you are using same compiler I worked ( CCS ).
If the case, there are some directives that allow we to get the PC current time.
Follows a piece of code I used to cath it to load DS1307 :

Code:
unsigned int8 Time[] = [B] __time__[/B]         ;
Check if compiler you´re working have a kind of similar built in macro in a #pragma directive.

+++

#### ivalex

##### Newbie level 4
ivalex,

I´m not sure if you are using same compiler I worked ( CCS ).
If the case, there are some directives that allow we to get the PC current time.
Follows a piece of code I used to cath it to load DS1307 :

Code:
unsigned int8 Time[] = [B] __time__[/B]         ;
Check if compiler you´re working have a kind of similar built in macro in a #pragma directive.

+++
yeah, im also using ccs compiler but the demo version only, i checked the pic-c help section and found that the #pragma is available to use, what should I do with it??

and the code that you provided, what are the values that will be placed in the time[]?

for further info, I checked and asked around from another forum also and they stated that the I wasn't actually calling the function localtime, or any time.h functions yet since the time.h file is something like a prototype only... so i tried including rtctime.c which was stated in the time.h comments but I don't know if what I did is right or wrong... T_T

#### andre_teprom

##### Super Moderator
Staff member
ivalex,

If you are using CCS, pragma directive don´t matter.
Just compile code bellow and you will see that local time is placed at Time[] variable in string format.

Code:
unsigned int8 Time[] =  __time__         ;
You can extract clock values with following code :

Code:
HourDecimal   = ( ( ( Time[0]-'0' ) * 10 ) + ( Time[1]-'0' ) ) ;
MinuteDecimal = ( ( ( Time[3]-'0' ) * 10 ) + ( Time[4]-'0' ) ) ;
SecondDecimal = ( ( ( Time[6]-'0' ) * 10 ) + ( Time[7]-'0' ) ) ;
Values pointed by index 2 and 5 refers to ":" character.

+++

Last edited:

#### Elvis8

##### Newbie level 6
Hi! can you extract the date???

#### andre_teprom

##### Super Moderator
Staff member
Yes, you can use the following code, that converts string to integer ( I decoded only to month variable ):

Code:
unsigned int8 Data[] =  __date__         ;
switch ( Data[3] )
{
case 'J' :
case 'j' :
if ( ( Data[4] == 'A' ) || ( Data[4] == 'a' ) )
{
MesDezena  = 0 ;
MesUnidade = 1 ;
}
else
{
if ( ( Data[5] == 'N' ) || ( Data[5] == 'n' ) )
{
MesDezena  = 0 ;
MesUnidade = 6 ;
}
else
{
MesDezena  = 0 ;
MesUnidade = 7 ;
}
}
break ;
///////////////////
case 'F' :
case 'f' :
MesDezena  = 0 ;
MesUnidade = 2 ;
break ;
///////////////////
case 'M' :
case 'm' :
switch ( Data[5] )
{
case 'R' :
case 'r' :
MesDezena  = 0 ;
MesUnidade = 3 ;
break ;
case 'I' :
case 'i' :
MesDezena  = 0 ;
MesUnidade = 5 ;
break ;
}
break ;
///////////////////
case 'A' :
case 'a' :
switch ( Data[4] )
{
case 'B' :
case 'b' :
MesDezena  = 0 ;
MesUnidade = 4 ;
break ;
case 'G' :
case 'g' :
MesDezena  = 0 ;
MesUnidade = 8 ;
break ;
}
break ;
///////////////////
case 'S' :
case 's' :
MesDezena  = 0 ;
MesUnidade = 9 ;
break ;
///////////////////
case 'O' :
case 'o' :
MesDezena  = 1 ;
MesUnidade = 0 ;
break ;
///////////////////
case 'N' :
case 'n' :
MesDezena  = 1 ;
MesUnidade = 1 ;
break ;
///////////////////
case 'D' :
case 'd' :
MesDezena  = 1 ;
MesUnidade = 2 ;
break ;
}
Despite some variables are not in english, will not hard to understand the meaning.

+++

Last edited:

Status
Not open for further replies.