Attempting To Build A SimpleIDE Library For The DS1302 RTC - Could Use A Little Help :)
idbruce
Posts: 6,197
I recently purchased a DS1302 module from Parallax for my current project. Of course I am a C and C++ guy, and the documentation for this module and language is somewhat lacking my needs, so I decided to write my own library. I initially started the groundwork for this library, loosely based upon a post by Rsadeika, which can be found here: https://forums.parallax.com/discussion/168949/ds1302-module-c-code
His or her code has resulted in the following:
Hearder file (.h):
And the C file (.c)
Please note that none of this code has been tested yet
I am currently working on the get_unix_time function. As the self describing function clearly states, I am attempting to obtain Unix time. In order to obtain a fairly accurate Unix time (meanwhile ensuring that this library is useful to others), I must determine whether the RTC is in 12 or 24 hour mode. There is other significant code and efforts that are associated with the DS1302 RTC chip, by the greatly missed Chris Savage, but they are for the BASIC Stamp, which can be downloaded from here (https://parallax.com/downloads/ds1302-basic-stamp-demo-code.
A little help writing this last function would surely be appreciated
His or her code has resulted in the following:
Hearder file (.h):
#include "simpletools.h" #include <time.h> //Included for the get_unix_time function //DS1302 Pin Usage #define DS1302_CS 1 #define DS1302_SCK 2 #define DS1302_IO 3 //DS1302 Time Registers #define DS1302_SECOND 0x80 #define DS1302_MINUTE 0x82 #define DS1302_HOUR 0x84 //DS1302 Date Registers #define DS1302_DATE 0x86 #define DS1302_MONTH 0x88 #define DS1302_YEAR 0x8C //DS1302 Day Register #define DS1302_DAY 0x8A //Read an individual DS1302 register value int read_ds1302(int ds1302_register); //Write an individual DS1302 register value void write_ds1302(int ds1302_register, int ds1302_value); //Set the DS1302 Hour register value void set_ds1302_hour(int hour_register_value); //Set the DS1302 Minute register value void set_ds1302_minute(int minute_register_value); //Set the DS1302 Second register value void set_ds1302_second(int second_register_value); //Set the DS1302 Date register value void set_ds1302_date(int date_register_value); //Set the DS1302 Month register value void set_ds1302_month(int month_register_value); //Set the DS1302 Year register value void set_ds1302_year(int year_register_value); //Set the DS1302 Day register value void set_ds1302_day(int day_register_value); //Get the DS1302 Hour register value int get_ds1302_hour(); //Get the DS1302 Minute register value int get_ds1302_minute(); //Get the DS1302 Second register value int get_ds1302_second(); //Get the DS1302 Date register value int get_ds1302_date(); //Get the DS1302 Month register value int get_ds1302_month(); //Get the DS1302 Year register value int get_ds1302_year(); //Get the DS1302 Day register value int get_ds1302_day(); //Get Unix time - The header file "time.h" has been included //specifically for this function // //Please note that in order to obtain fairly accurate //Unix time, the DS1302 registers must be set according //Coordinated Universal Time (or UTC), otherwise programming //must compensate for time zone differences. For further //information, please research Unix Time int get_unix_time();
And the C file (.c)
#include "simpletools.h" int read_ds1302(int ds1302_register) { int read_register_value; int result; read_register_value = ds1302_register + 1; high(DS1302_CS); shift_out(DS1302_IO, DS1302_SCK, LSBFIRST, 8, read_register_value); result = shift_in(DS1302_IO, DS1302_SCK, LSBPRE, 8); low(DS1302_CS); return result; } void write_ds1302(int ds1302_register, int ds1302_value) { high(DS1302_CS); shift_out(DS1302_IO, DS1302_SCK, LSBFIRST, 8, ds1302_register); shift_out(DS1302_IO, DS1302_SCK, LSBFIRST, 8, ds1302_value); low(DS1302_CS); } void set_ds1302_hour(int hour_register_value) { write_ds1302(DS1302_HOUR, hour_register_value); } void set_ds1302_minute(int minute_register_value) { write_ds1302(DS1302_MINUTE, minute_register_value); } void set_ds1302_second(int second_register_value) { write_ds1302(DS1302_SECOND, second_register_value); } void set_ds1302_date(int date_register_value) { write_ds1302(DS1302_DATE, date_register_value); } void set_ds1302_month(int month_register_value) { write_ds1302(DS1302_MONTH, month_register_value); } void set_ds1302_year(int year_register_value) { write_ds1302(DS1302_YEAR, year_register_value); } void set_ds1302_day(int day_register_value) { write_ds1302(DS1302_DAY, day_register_value); } int get_ds1302_hour() { return read_ds1302(DS1302_HOUR); } int get_ds1302_minute() { return read_ds1302(DS1302_MINUTE); } int get_ds1302_second() { return read_ds1302(DS1302_SECOND); } int get_ds1302_date() { return read_ds1302(DS1302_DATE); } int get_ds1302_month() { return read_ds1302(DS1302_MONTH); } int get_ds1302_year() { return read_ds1302(DS1302_YEAR); } int get_ds1302_day() { return read_ds1302(DS1302_DAY); } long get_unix_time() { struct tm t; time_t unix_time; t.tm_year = get_ds1302_year() - 1900; t.tm_mon = get_ds1302_month(); t.tm_mday = get_ds1302_day(); t.tm_hour = 16; t.tm_min = get_ds1302_minute(); t.tm_sec = get_ds1302_second(); //Is Daylight Saving Time in effect? -1 = Unknown, 0 = No, 1 = Yes t.tm_isdst = -1; unix_time = mktime(&t); return (long)unix_time; }
Please note that none of this code has been tested yet
I am currently working on the get_unix_time function. As the self describing function clearly states, I am attempting to obtain Unix time. In order to obtain a fairly accurate Unix time (meanwhile ensuring that this library is useful to others), I must determine whether the RTC is in 12 or 24 hour mode. There is other significant code and efforts that are associated with the DS1302 RTC chip, by the greatly missed Chris Savage, but they are for the BASIC Stamp, which can be downloaded from here (https://parallax.com/downloads/ds1302-basic-stamp-demo-code.
A little help writing this last function would surely be appreciated
Comments
Mike
As far as I can tell, your code does not handle the 12 or 24 hour mode, which is the reason for my post.
Ken Gracey
My goal was and still is to write a simple, easy to understand library, which most users could easily modify to suit their needs, and post it here, with appropriate licensing.
Being "complete" is quite a different issue and would require a few more functions to read and write the Burst Mode, Trickle Charge, and Clock Halt registers, and I am sure there is more.
I am more of a PC programmer than a microcontroller programmer, so we would need a bit banger or two to jump in here.
However, you are certainly welcome to the end result whatever it may become, "complete" or incomplete
www.maximintegrated.com/en/products/analog/real-time-clocks/DS1302.html
https://datasheets.maximintegrated.com/en/ds/DS1302.pdf
Table 3 shows the layout of the registers. The values are in BCD format.
I have some SPIN code I wrote for a larger project if your interested. It reads and writes most the clock registers. Has a simple terminal interface for setting the date/time interactively and a somewhat unique method for displaying the data/time string.
It's still a work in progress.
I looked at the burst mode and memory functions that seem nice but offer very little to the product. It's not like it's an IMU and we need to constantly read the values in a timely manner.
Mike
Thanks for the heads up on the accuracy. I just purchased the DS1302 module from Parallax, so I think I will work on the code and experiment with that a little before swapping it out.
Ken
I have been looking very closely at Chris Savage's example code for the DS1302 and I now believe that it should be very easy to port it to the Propeller, in fact I have just started to swap the code. The main difference between his code and what I was attempting is that he used the burst mode for both his read from and writes to the DS1302, which should be perfectly fine for your customers.
For inside a home, the unit is relatively reliable, after you do the initial recalibration via the program code. For your general testing and code development, it should suffice.
Ray
Also my logging project shows how it can be used.
Mike
Mike
Not sure if there are any revelations in the following but I just stumbled across it.
The code examples are in line-numbered BASIC but easy enough to follow and I'm sure easily downgraded converted to c.
At this point, I have a fairly decent grasp of what is required, and I have written four functions, burst write, burst read, individual value write, and individual value read. The functions are currently working, except for having the data in the proper format. I know this is true, by testing with other firmware.
I am currently sidetracked from setting the proper format because I recently learned of the compiler's preprocessor macros for _DATE_ and _TIME_. I want to use these values to set the RTC, so that people will not have to code it manually. In other words, just compile the program, run the program, and the RTC will be set according to the PCs clock. However, before compiling and running the program, the user will have constants that can be modified to meet their particular requirements. Additionally, I am sure there will be a need for a time offset to adjust for the difference between compile and runtime, and this will also be a constant that can be modified. That is providing I find a way to copy these values If I use these values outside of a "print" statement, the compiler complains that they are not defined. So I am currently looking into printing them to the terminal and then reading them back. However, it may be possible some other way with a proper include or something.
Anyhow, as always, I do appreciate your input.
EDIT: This works and the compiler does not complain I thought of it earlier, but did not try it because I got sleepy.
I believe my previous post indicated this fact. At this point, my "time offset" would need to be about 2~3 seconds, but that will change.