|
|
View previous topic :: View next topic |
Author |
Message |
Phil
Joined: 09 Sep 2003 Posts: 12
|
Another DS1307 driver |
Posted: Wed Jun 15, 2005 8:48 am |
|
|
I've found some Ds1307 code from Tullos and changed it to work easier for my application. It's a very basic driver just for setting and reading the date & time. Tested on PIC 18F452 with hardware I2C, hope some people will find it usefull.
Code: |
////////////////////////////////////////////////////////////////////////////////
/// DS1307.C ///
/// Driver for Real Time Clock ///
/// ///
/// ds1307_init() - Enable oscillator without clearing the seconds register -///
/// used when PIC loses power and DS1307 run from 3V BAT ///
/// - Disable squarewave output ///
/// ///
/// ds1307_set_date_time(day,mth,year,dow,hour,min,sec) Set the date/time ///
/// ///
/// ds1307_get_date(day,mth,year,dow) Get the date ///
/// ///
/// ds1307_get_time(hr,min,sec) Get the time ///
/// ///
////////////////////////////////////////////////////////////////////////////////
#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(0x80); // Disable squarewave output pin
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;
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(0x80); // REG 7 - Disable squarewave output pin
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() & 0x7f);
min = bcd2bin(i2c_read() & 0x7f);
hr = bcd2bin(i2c_read(0) & 0x3f);
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));
}
|
Example use:
Code: |
#include <18F452.h>
#device adc=8
#fuses NOWDT,WDT128,HS, NOPROTECT, NOOSCSEN, BROWNOUT, BORV20, NOPUT, STVREN, NODEBUG, NOLVP, NOWRT, NOWRTD, NOWRTB, NOWRTC, NOCPD, NOCPB, NOEBTR, NOEBTRB
#use delay(clock=20000000,RESTART_WDT)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=PC,errors)
#include <ds1307.c>
void main()
{
BYTE sec;
BYTE min;
BYTE hrs;
BYTE day;
BYTE month;
BYTE yr;
BYTE dow;
ds1307_init();
// Set date for -> 15 June 2005 Tuesday
// Set time for -> 15:20:55
ds1307_set_date_time(15,6,5,2,15,20,55);
while(1)
{
delay_ms(1000);
ds1307_get_date(day,month,yr,dow);
ds1307_get_time(hrs,min,sec);
printf("\f\%02d/\%02d/\%02d\r\n",day,month,yr);
printf("\%02d:\%02d:\%02d", hrs,min,sec);
}
}
|
|
|
|
Charles Linquist
Joined: 07 May 2005 Posts: 28 Location: Campbell, CA
|
|
Posted: Sun Jun 19, 2005 10:45 pm |
|
|
When I try to compile the code, on the line
#use I2C(master,sda=RTC_SDA, scl=RTC_SCL)
I get the error:
Use parameter is out of range: Not a number PIN_C4
Does anyone know why I would be getting this error? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 19, 2005 11:19 pm |
|
|
In this thread, you suggest that your next project will use a 16F818.
http://www.ccsinfo.com/forum/viewtopic.php?t=23222
The 16F818 has no Port C, so the compiler gives an error if you specify
pins PIN_C3 and PIN_C4 in the #use i2c() statement. |
|
|
Charles Linquist
Joined: 07 May 2005 Posts: 28 Location: Campbell, CA
|
|
Posted: Sun Jun 19, 2005 11:26 pm |
|
|
Don't know where you got that idea. The only chip I use is a 18F8720, although I have used an 18F452 in the past.
I changed the header file to
#include <18F8720.h>
No luck. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jun 20, 2005 12:13 am |
|
|
It compiled OK for me. I saved the first portion as ds1307.c and
put it in the project folder. I saved the 2nd portion as Test.c and
it also went in the project folder. It gave an error on the #fuses
statement because the 18F8720 has different fuses than the 18F452,
so I commented out that statement for the purposes of this test.
The only change to the 2nd portion of code was to change 18F452.h to
18F8720.h as shown below. If you still get the error, then check
your 18F8720.h file and make sure that PIN_C3 and PIN_C4 are
defined in it.
Code: |
#include <18F8720.h>
#device adc=8
//#fuses NOWDT,WDT128,HS, NOPROTECT, NOOSCSEN, BROWNOUT, BORV20, NOPUT, STVREN, NODEBUG, NOLVP, NOWRT, NOWRTD, NOWRTB, NOWRTC, NOCPD, NOCPB, NOEBTR, NOEBTRB
#use delay(clock=20000000,RESTART_WDT)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=PC,errors)
#include <ds1307.c>
void main()
{ |
|
|
|
densimitre
Joined: 21 Dec 2004 Posts: 45
|
|
Posted: Wed Apr 25, 2007 11:14 am |
|
|
Charles Linquist wrote: | When I try to compile the code, on the line
#use I2C(master,sda=RTC_SDA, scl=RTC_SCL)
I get the error:
Use parameter is out of range: Not a number PIN_C4
Does anyone know why I would be getting this error? |
put following code:
Code: | #include <ds1307.h>
#use I2C(MULTI_MASTER,sda=RTC_SDA, scl=RTC_SCL)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=PC,errors)
|
the compiler read first definitions of ds1307.h file, for use it after in #use I2C..
Try and will see all OK when compiling...
by.. |
|
|
rfreddy
Joined: 03 Jun 2007 Posts: 7
|
|
Posted: Fri Jun 15, 2007 3:21 pm |
|
|
Has anybody tried this code in a 16f877?, I'm actually using on it but I'm unable to set the date and time correctly. Any idea?
Thanks,
Freddy. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jun 15, 2007 3:40 pm |
|
|
1. Make sure that you call the ds1307_init() routine.
2. Make sure you have a 3v lithium battery connected between
the Vbat pin and ground.
3. Make sure you have pull-up resistors on SDA and SCL. |
|
|
Ami
Joined: 02 Sep 2007 Posts: 5 Location: Venezuela
|
where I find ds1307.h? |
Posted: Sat Sep 22, 2007 9:40 am |
|
|
hi, im trying to compile the routine on top, does it works for 18f4550? |
|
|
hadeelqasaimeh
Joined: 05 Jan 2006 Posts: 105
|
|
Posted: Sat Nov 03, 2007 6:44 am |
|
|
its work fine with this driver
but this mean i must set clock every run!!!!!!!
how to avoid this? |
|
|
hadeelqasaimeh
Joined: 05 Jan 2006 Posts: 105
|
|
Posted: Sun Nov 04, 2007 11:18 am |
|
|
hadeelqasaimeh wrote: | its work fine with this driver
but this mean i must set clock every run!!!!!!!
how to avoid this? |
hi ,i replace ds1307 initialization by this
Code: |
output_float(RTC_SCL);
output_float(RTC_SCL);
|
and it will not need setting time anymore
any idea? |
|
|
razorhash
Joined: 10 Jun 2008 Posts: 1
|
Thanks |
Posted: Wed Jun 25, 2008 5:06 am |
|
|
Thanks alot buddy...
Probably the simplest working code Ive seen online..
thanks again.. |
|
|
pattousai
Joined: 23 Aug 2006 Posts: 37
|
|
Posted: Tue Aug 19, 2008 7:21 pm |
|
|
why the squarewave output pin is disabled in the init() and set_date_time()?
if i want a squarewave of 1Hz i'm only have to replace the
to
is that right?
thanks |
|
|
Phil
Joined: 09 Sep 2003 Posts: 12
|
|
Posted: Wed Aug 20, 2008 5:36 am |
|
|
To ENABLE 1Hz squarewave you need to write 0x10 (00010000b), if you check the datasheet you will see that to enable the squarewave output you need to set bit4 in the control REG and for 1Hz output bit0 & bit1 needs to be zero in the control REG!
Regards |
|
|
pattousai
Joined: 23 Aug 2006 Posts: 37
|
|
Posted: Wed Aug 20, 2008 10:21 am |
|
|
thanks Phil,
i had check the datasheet, it was just a type error, but thanks again |
|
|
|
|
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
|