Show Posts
|
|
Pages: 1 ... 3 4 [5] 6 7 ... 13
|
|
62
|
Forum 2005-2010 (read only) / Development / Re: Library for DS1307 Real Time Clock
|
on: October 18, 2007, 12:50:19 pm
|
Here is a little usage example for alarms and some other stuff: void setup() { // Set the clock using a unix time stamp (date -u +'%s') RTC.clockSet(1192390068); //Sun Oct 14 15:27:48 EDT 2007 // Setup a callback function for the integrity check // See below for the callback functions RTC.clockIntegrityCallback(integrityCallback); // Enable the Square Wave @ 1Hz on INTB RTC.sqwSetRate(DS1337_SQW_1HZ); RTC.sqwEnable(); // Setup the first alarm RTC.alarmSelect(0); // Switch to alarm 2 RTC.alarmSet(RTC_SEC, 30); RTC.alarmSet(RTC_MIN, 18); RTC.alarmSet(RTC_HR, 0); RTC.alarmSet(RTC_DOW, 0); // Match mode: every minutes and seconds RTC.alarmSet(DS1337_ALARM_MODE, DS1337_ALARM_MCH_MINSEC); // Setup callback function for alarm 1 RTC.alarmSetCallback(alarmCallback1); // Setuo the external interrupt on INTA for alarm1 RTC.alarmSetInterrupt(); RTC.alarmSelect(1); // Switch to alarm 2 // Match mode: once per minute at 00s RTC.alarmSet(DS1337_ALARM_MODE, DS1337_ALARM_PER_MIN); // Setup callback function for alarm 2 RTC.alarmSetCallback(alarmCallback2); // Setup the interrupt for alarm 2 // If the square wave is enabled, it will output on INTA // if the SQW is disabled the interrupt will happen on INTB RTC.alarmSetInterrupt(); }
void loop() { RTC.clockChecks(); // Performs alarm and integrity checks for call back functions }
// Note that the alarm registers will stay high // until these function are finished executing. void alarmCallback1(void) { Serial.print("alarm 1 triggerd"); return; } void alarmCallback2(void) { Serial.print("alarm 2 triggerd"); return; }
void integrityCallback(void) { Serial.print("Oscillator integrity fault!"); // If the fault flag is high the clock is stopped // so in this function we can fix the time and start the clock again RTC.clockStart(); return; }
There are other stuff too obvious, such as manually checking for alarms, setting the time in binary, etc. Most of the options can be turned on/off to save some space if you don't need the functionality. You should try and go through the two configuration files (ds1337.h, configs/ds1337/ds1337.h and configs/RTC/rtcConfig.h) there are a lot of helpful comments in there.
|
|
|
|
|
63
|
Forum 2005-2010 (read only) / Development / Re: Library for DS1307 Real Time Clock
|
on: October 18, 2007, 12:23:14 pm
|
Hehehe, don't get me wrong Mattt, I did spend a lot of time on this thing in the past few days (I should really say nights). – Oh man that Unix Time Stamp function grrrrrrrrr – And I still should split out the RTC stuff from the DS1337 and make the thing a little more generic so it can easily be adapted to other RTC's without changing anything in the business logic. Sorry for the 404, here's the file: http://svn.mlalonde.net/cral/configs/RTC/rtcConfig.h. There's also a Trac site at http://trac.mlalonde.net/cral/. There's not much there yet but I'll try and really document all my libraries and add them to the site so they are easily available  And of course they are free for anyone to use (MIT license if you want to know) EDIT: Oh yeah there is now full support for alarms, alarm interrupts, alarm user defined callback functions, and the square wave output. I've also put back the clockStart/Stop routines when changing the time, this resets the status register and helps reduce possible errors of either the two alarm flags or the fault flag.
|
|
|
|
|
65
|
Forum 2005-2010 (read only) / Development / Re: Library for DS1307 Real Time Clock
|
on: October 16, 2007, 12:14:42 pm
|
Code size is obviously bigger than using a function. On the other hand it's not only obviously faster (no call) it also reduces the function stack and parameter passing. So you really have to see what you need. I actually ended up switch that back to a function cause it was called many times and saved up something like 20~30 bytes (for both bintobcd and bcdtobin). Hope this helps 
|
|
|
|
|
67
|
Forum 2005-2010 (read only) / Development / Re: Library for DS1307 Real Time Clock
|
on: October 14, 2007, 08:14:00 pm
|
Rest of "ds1337.cpp": void DS1337::clockSetWithUTS(uint32_t unixTimeStamp, boolean correctedTime) { uint16_t leapCorrection = 0; uint32_t tt; uint8_t thisDate; int ii; #if defined(RTC_DST_TYPE) uint16_t thisYear; #endif uint16_t year; const uint16_t monthcount[] = {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; /** * Calculate GMT and DST **/ #if defined(RTC_GMT_OFFSET) if (!correctedTime) unixTimeStamp = unixTimeStamp + (RTC_GMT_OFFSET * 3600); #endif
// Years tt = unixTimeStamp / 3600 / 24 / 365; year = tt + 1970; #if defined(RTC_DST_TYPE) if (!correctedTime) { thisYear = year; } #endif // Set the century bit if (tt > 30) { rtc_bcd[DS1337_MTH] = (rtc_bcd[DS1337_MTH] | DS1337_LO_CNTY); tt-= 30; } else { rtc_bcd[DS1337_MTH] = (rtc_bcd[DS1337_MTH] & ~DS1337_LO_CNTY); } // Set the year rtc_bcd[DS1337_YR] = binToBcd(tt); // Number of days left in the year tt = (unixTimeStamp%31536000 / 3600 / 24) + 1; // leap year correction for (year--; year > 1970; year--) { if (isleap(year)) { leapCorrection++; tt--; } } // Set the month for (ii = 1; ii < 12; ii++) { if (monthcount[ii+1] > (tt + ((ii == 2 && isleap(thisYear)) * 1))) { rtc_bcd[DS1337_MTH] = (binToBcd(ii) & ~DS1337_LO_CNTY) | (rtc_bcd[DS1337_MTH] & DS1337_LO_CNTY); break; } } // Date #if defined(RTC_DST_TYPE) if (!correctedTime) { thisDate = tt - monthcount[ii]; } #endif rtc_bcd[DS1337_DATE] = binToBcd(tt - monthcount[ii]); // Day of the week rtc_bcd[DS1337_DOW] = ((tt)%7 + 1) & DS1337_LO_DOW; // Hour tt = unixTimeStamp%86400 / 3600; rtc_bcd[DS1337_HR] = binToBcd(tt); #if defined(RTC_DST_TYPE) if (!correctedTime) { uint8_t dstStartMo, dstStopMo, dstStart, dstStop; #ifndef RTC_CHECK_OLD_DST dstStart = (31-((thisYear * 5 / 4) + 1) % 7); #if RTC_DST_TYPE == 1 dstStop = (31-((thisYear * 5 / 4) + 1) % 7); // EU DST #else dstStop = 7 - ((1 + thisYear * 5 / 4) % 7); // US DST #endif dstStartMo = 3; dstStopMo = 11; #else if (thisYear < 2006) { dstStart = (2+6 * thisYear - (thisYear / 4) ) % 7 + 1; dstStop = 14 - ((1 + thisYear * 5 / 4) % 7); dstStartMo = 4; dstStopMo = 10; } else { dstStart = (31-((thisYear * 5 / 4) + 1) % 7); #if RTC_DST_TYPE == 1 dstStop = (31-((thisYear * 5 / 4) + 1) % 7); // EU DST #else dstStop = 7 - ((1 + thisYear * 5 / 4) % 7); // US DST #endif dstStartMo = 3; dstStopMo = 11; } #endif if (ii >= dstStartMo && ii <= dstStopMo) { if (ii < dstStopMo) { if (ii > dstStartMo || thisDate > dstStart || thisDate == dstStart && tt >= 2) { clockSetWithUTS(unixTimeStamp + 3600, true); return; } } else { if (thisDate < dstStop || thisDate == dstStop && tt < 2) { clockSetWithUTS(unixTimeStamp + 3600, true); return; } } } } #endif // Minutes tt = unixTimeStamp%3600 / 60; rtc_bcd[DS1337_MIN] = binToBcd(tt); // Seconds tt = (unixTimeStamp%3600)%60; rtc_bcd[DS1337_SEC] = binToBcd(tt); // Stop the clock //clockStop(); // Save buffer to the RTC clockSave(); // Restart the oscillator //clockStart(); }
void DS1337::printRegisters(void) { for(int ii=0;ii<0x10;ii++) { SPrint("0x"); Serial.print(ii, HEX); SPrint(" "); Serial.println(getRegister(ii), BIN); }
delay(200); }
EDIT: No need to stop/start the oscillator when reading or writing to the ds1337 as the IC as in internal buffer and it will read/write only when all of the memory is read for the operation. Also, if the scan mod is used the clock is always started when the address is found and the osc. is stopped.
|
|
|
|
|
68
|
Forum 2005-2010 (read only) / Development / Re: Library for DS1307 Real Time Clock
|
on: October 14, 2007, 08:13:32 pm
|
Driver "ds1337.cpp": extern "C" { #include <Wire/Wire.h> #include <avr/pgmspace.h> #include <HardwareSerial.h> }
#include "programStrings.h" #include "ds1337.h" #include "rtcConfig.h"
DS1337::DS1337() { #ifdef WIRE_LIB_SCAN_MOD clockExists = false; #endif Wire.begin(); }
DS1337 RTC = DS1337();
#ifdef WIRE_LIB_SCAN_MOD int8_t DS1337::clockInit(void) { // Account for the crystal power up! delay(250); // Check address and returns false is there is an error if (Wire.checkAddress(DS1337_WADDR)) { // Possibly set the default registers here clockExists = true; // Start the oscillator if need if (getRegisterBit(DS1337_SP, DS1337_SP_EOSC)) { clockStart(); } return DS1337_WADDR; } else clockExists = false; return -1; } #endif
void DS1337::setRegister(uint8_t registerNumber, uint8_t registerMask) { writeRegister(registerNumber, (getRegister(registerNumber) | registerMask)); }
void DS1337::unsetRegister(uint8_t registerNumber, uint8_t registerMask) { writeRegister(registerNumber, (getRegister(registerNumber) & ~registerMask)); }
void DS1337::writeRegister(uint8_t registerNumber, uint8_t registerValue) { Wire.beginTransmission(DS1337_WADDR); Wire.send(registerNumber); Wire.send(registerValue); Wire.endTransmission(); }
uint8_t DS1337::getRegister(uint8_t registerNumber) { Wire.beginTransmission(DS1337_WADDR); Wire.send(registerNumber); Wire.endTransmission(); Wire.requestFrom(DS1337_WADDR, 1); return Wire.receive(); }
// PRIVATE FUNCTIONS void DS1337::clockRead(void) { Wire.beginTransmission(DS1337_WADDR); Wire.send(0x00); Wire.endTransmission();
Wire.requestFrom(DS1337_WADDR, 7); for(int i=0; i<7; i++) { if (Wire.available()) rtc_bcd[i] = Wire.receive(); } }
void DS1337::clockSave(void) { Wire.beginTransmission(DS1337_WADDR); Wire.send(0x00); for(int i=0; i<7; i++) { Wire.send(rtc_bcd[i]); } Wire.endTransmission(); }
// PUBLIC FUNCTIONS void DS1337::clockGet(uint16_t *rtc) { clockRead(); for(int i=0;i<8;i++) // cycle through each component, create array of data { rtc[i]=clockGet(i, 0); } }
uint16_t DS1337::clockGet(uint8_t c, boolean refresh) { if(refresh) clockRead(); int timeValue=-1; switch(c) { case DS1337_SEC: timeValue = (10*((rtc_bcd[DS1337_SEC] & DS1337_HI_SEC)>>4))+(rtc_bcd[DS1337_SEC] & DS1337_LO_BCD); break; case DS1337_MIN: timeValue = (10*((rtc_bcd[DS1337_MIN] & DS1337_HI_MIN)>>4))+(rtc_bcd[DS1337_MIN] & DS1337_LO_BCD); break; case DS1337_HR: timeValue = (10*((rtc_bcd[DS1337_HR] & DS1337_HI_HR)>>4))+(rtc_bcd[DS1337_HR] & DS1337_LO_BCD); break; case DS1337_DOW: timeValue = rtc_bcd[DS1337_DOW] & DS1337_LO_DOW; break; case DS1337_DATE: timeValue = (10*((rtc_bcd[DS1337_DATE] & DS1337_HI_DATE)>>4))+(rtc_bcd[DS1337_DATE] & DS1337_LO_BCD); break; case DS1337_MTH: timeValue = (10*((rtc_bcd[DS1337_MTH] & DS1337_HI_MTH)>>4))+(rtc_bcd[DS1337_MTH] & DS1337_LO_BCD) & ~DS1337_LO_CNTY; break; case DS1337_YR: timeValue = (10*((rtc_bcd[DS1337_YR] & DS1337_HI_YR)>>4))+(rtc_bcd[DS1337_YR] & DS1337_LO_BCD)+(1900 + (rtc_bcd[DS1337_MTH] & DS1337_LO_CNTY ? 100 : 0)); break; case DS1337_CNTY: timeValue = rtc_bcd[DS1337_MTH] & DS1337_LO_CNTY>>7; break; } // end switch return timeValue; }
void DS1337::clockSet(uint8_t timeSection, uint16_t timeValue) { switch(timeSection) { case DS1337_SEC: if(timeValue<60 && timeValue>-1) { rtc_bcd[DS1337_SEC] = binToBcd(timeValue); } break; case DS1337_MIN: if(timeValue<60 && timeValue>-1) { rtc_bcd[DS1337_MIN] = binToBcd(timeValue); } break; case DS1337_HR: // TODO : AM/PM 12HR/24HR if(timeValue<24 && timeValue>-1) { rtc_bcd[DS1337_HR] = binToBcd(timeValue); } break; case DS1337_DOW: if(timeValue<8 && timeValue>-1) { rtc_bcd[DS1337_DOW] = timeValue; } break; case DS1337_DATE: if(timeValue<31 && timeValue>-1) { rtc_bcd[DS1337_DATE] = binToBcd(timeValue); } break; case DS1337_MTH: if(timeValue<13 && timeValue>-1) { rtc_bcd[DS1337_MTH] = (binToBcd(timeValue) & ~DS1337_LO_CNTY) | (rtc_bcd[DS1337_MTH] & DS1337_LO_CNTY); } break; case DS1337_YR: if(timeValue<1000 && timeValue>-1) { rtc_bcd[DS1337_YR] = binToBcd(timeValue); } break; case DS1337_CNTY: if (timeValue > 0) { rtc_bcd[DS1337_MTH] = (rtc_bcd[DS1337_MTH] | DS1337_LO_CNTY); } else { rtc_bcd[DS1337_MTH] = (rtc_bcd[DS1337_MTH] & ~DS1337_LO_CNTY); } break; } // end switch clockSave(); }
uint32_t DS1337::calculateUTS(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec) { /* Number of days per month */ uint32_t tt; const uint16_t monthcount[] = {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; /* Compute days */ tt = (year - 1970) * 365 + monthcount[month] + day - 1; /* Compute for leap year */ for (month <= 2 ? year-- : 0; year >= 1970; year--) if (isleap(year)) tt++; /* Plus the time */ tt = sec + 60 * (min + 60 * (tt * 24 + hour - RTC_GMT_OFFSET)); return tt; }
Rest to follow....
|
|
|
|
|
69
|
Forum 2005-2010 (read only) / Development / Re: Library for DS1307 Real Time Clock
|
on: October 14, 2007, 08:12:42 pm
|
Header file "ds1337.h": /* DS1337.h - library for DS1337 rtc */
// ensure this library description is only included once #ifndef DS1337_h #define DS1337_h
// include types & constants of Wiring core API #include <WConstants.h>
// include types & constants of Wire ic2 lib #include <Wire/Wire.h>
#include "rtcConfig.h"
#define DS1337_SEC 0 #define DS1337_MIN 1 #define DS1337_HR 2 #define DS1337_DOW 3 #define DS1337_DATE 4 #define DS1337_MTH 5 #define DS1337_YR 6 #define DS1337_CNTY 7
#define RTC_SEC DS1337_SEC #define RTC_MIN DS1337_MIN #define RTC_HR DS1337_HR #define RTC_DOW DS1337_DOW #define RTC_DATE DS1337_DATE #define RTC_MTH DS1337_MTH #define RTC_YR DS1337_YR #define RTC_CNTY DS1337_CNTY
#define DS1337_WADDR 0x68 #define DS1337_RADDR DS1337_WADDR | 0x01
/** * Define register bit masks **/ #define DS1337_LO_BCD B00001111 #define DS1337_HI_BCD B01110000
#define DS1337_HI_SEC B01110000 #define DS1337_HI_MIN B01110000 #define DS1337_HI_HR B00110000 #define DS1337_LO_DOW B00000111 #define DS1337_HI_DATE B00110000 #define DS1337_HI_MTH B00010000 #define DS1337_LO_CNTY B10000000 #define DS1337_HI_YR B11110000
#define DS1337_ARLM1 0x07 #define DS1337_ARLM1_LO_SEC B00001111 #define DS1337_ARLM1_HI_SEC B01110000 #define DS1337_ARLM1_LO_MIN B01110000 #define DS1337_ARLM1_HI_MIN B00001111
#define DS1337_SP 0x0E #define DS1337_SP_EOSC B10000000 #define DS1337_SP_RS2 B00010000 #define DS1337_SP_RS1 B00001000 #define DS1337_SP_INTCN B00000100 #define DS1337_SP_A2IE B00000010 #define DS1337_SP_A1IE B00000001
#define DS1337_STATUS 0x0F #define DS1337_STATUS_OSF B10000000 #define DS1337_STATUS_A2F B00000010 #define DS1337_STATUS_A1F B00000001
/** * Macros **/ #define clockStart() unsetRegister(DS1337_SP, DS1337_SP_EOSC) #define clockStop() setRegister(DS1337_SP, DS1337_SP_EOSC)
#define getRegisterSP() getRegisterSP(DS1337_SP) #define getRegisterStatus() getRegisterStatus(DS1337_STATUS)
#define getRegisterBit(reg, bitMask) getRegister(reg) & bitMask
#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
#define bcdToBin(val) (((val)&15) + ((val)>>4)*10) #define binToBcd(val) ((((val)/10)<<4) + (val)%10)
/** * getUTS: Macro for calculateUTS * returns the time as a unix time stamp * This function doesn't take into account having DST set or not! **/ #define getUTS(refresh) calculateUTS( RTC.clockGet(DS1337_YR, true), RTC.clockGet(DS1337_MTH, false), \ RTC.clockGet(DS1337_DATE, false), RTC.clockGet(DS1337_HR, false), \ RTC.clockGet(DS1337_MIN, false), RTC.clockGet(DS1337_SEC, false) \ )
#define clockSet(UTS) clockSetWithUTS(UTS, false)
// library interface description class DS1337 { // user-accessible "public" interface public: /** * clockExists: keeps track of the whether or not the RTC exists **/ #ifdef WIRE_LIB_SCAN_MOD bool clockExists; #endif /** * Class constructor **/ DS1337(); /** * clockInit: initializes the clock * If the I2C scan mod is available, it'll verify the RTC is reachable **/ int8_t clockInit(void); /** * setRegister: sets a register bit fromt he register number and bitmask **/ void setRegister(uint8_t, uint8_t); /** * unsetRegister: unsets a register bit fromt he register number and bitmask **/ void unsetRegister(uint8_t, uint8_t); /** * getRegister: returns the specified register **/ uint8_t getRegister(uint8_t); /** * clockGet: fills an array with the current time data **/ void clockGet(uint16_t *); /** * clockGet: gets a specific item from the clock buffer * use the second param to specify a buffer refresh **/ uint16_t clockGet(uint8_t, boolean); /** * calculateUTS: returns the time as a unix time stamp * This function doesn't take into account having DST set or not! **/ uint32_t calculateUTS(uint16_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t); /** * clockSetWithUTS: sets the date & time from a unix time stamp * pass the second param as true to skip DTS and GMT calculation **/ void clockSetWithUTS(uint32_t, boolean); /** * clockSet: Set the clock time using integer values **/ void clockSet(uint8_t, uint16_t); /** * Prints all of the DS1337 registers **/ void printRegisters(void); private: uint8_t rtc_bcd[8]; void writeRegister(uint8_t, uint8_t); void clockSave(void); void clockRead(void); };
extern DS1337 RTC;
#endif
|
|
|
|
|
70
|
Forum 2005-2010 (read only) / Development / Re: Library for DS1307 Real Time Clock
|
on: October 14, 2007, 08:07:26 pm
|
Here it is.. the whole library. It includes a test in the init to detect the RTC (if you have the I2C scanner mod I posted here). Setting the time using the old method or the new epoch functions which also calculates US and EU (even pre 2006 if needed!) DST and calculates the GMT offset (configurable at compile). And yes that function is almost as big as the rest of the driver! The old way of getting the time is still the current one as it's a lot more practical for printing in a strftime-less environment. But for good measure I added a way to get the current Epoch (*doesn't care about dst!*, but if you need that it should be easy to fix). My only issue right now is that OSCF (oscillator flag), which would be nice for the original time setting condition. But the time seems to stay accurate (at least after a few hours). The RTC config "rtcConfig.h": #ifndef RTC_CONFIG_H #defin#ifndef RTC_CONFIG_H #define RTC_CONFIG_H
/** * Set this to your local GMT offset * Comment to skip GMT offset calculations **/ #define RTC_GMT_OFFSET -5
/** * Select your DST type * Comment all to skip DST calculation **/ #define RTC_DST_TYPE 0 /* US */ //#define RTC_DST_TYPE 1 /* EU */
// Uncomment this only if you need to check DST prior to 2006 //#define RTC_CHECK_OLD_DST
#define RTC_DOW_1 PSTR("Sun") /* First day of the week */ #define RTC_DOW_2 PSTR("Mon") #define RTC_DOW_3 PSTR("Tue") #define RTC_DOW_4 PSTR("Wed") #define RTC_DOW_5 PSTR("Thu") #define RTC_DOW_6 PSTR("Fri") #define RTC_DOW_7 PSTR("Sat")
#define RTC_DOW_0 RTC_DOW_4 /* Wednesday is the first day of Epoch: This probably shouldn't change! */
#endif
Rest to follow.... EDIT: Pre 2006 check is now optional to save space.
|
|
|
|
|
71
|
Forum 2005-2010 (read only) / Development / Re: Library for DS1307 Real Time Clock
|
on: October 13, 2007, 03:50:37 pm
|
Got it  Apparently the internal xtal's capacitance already matched the DS's internal caps. But I had two 22pF caps there... removed them and bam  I'll post some more code and stuff a bit later EDIT: this may still not be perfect, the xtal might want some caps, cause the OSF flag is always risen and the possible reasons are 1) The first time power is applied. 2) The voltage present on VCC is insufficient to support oscillation. 3) The [not]EOSC bit is turned off. 4) External influences on the crystal (e.g., noise, leakage, etc.). It's not the first time power is applied, vcc is fine, EOSC is turned off (note reason 2 has [not]!). So that leaves only reason 4. But is seems to work just fine. I'm fooling around with some Epoch code as we speak.
|
|
|
|
|
74
|
Forum 2005-2010 (read only) / Development / Re: Library for DS1307 Real Time Clock
|
on: October 12, 2007, 10:59:35 pm
|
I forgot the header file. /* DS1337.h - library for DS1337 rtc */
// ensure this library description is only included once #ifndef DS1337_h #define DS1337_h
// include types & constants of Wiring core API #include <WConstants.h>
// include types & constants of Wire ic2 lib #include <Wire/Wire.h>
#define DS1337_SEC 0 #define DS1337_MIN 1 #define DS1337_HR 2 #define DS1337_DOW 3 #define DS1337_DATE 4 #define DS1337_MTH 5 #define DS1337_YR 6
#define DS1337_BASE_YR 2000
#define DS1337_CTRL_ID B1101000
// Define register bit masks #define DS1337_CLOCKHALT B10000000 #define DS1337_LO_BCD B00001111 #define DS1337_HI_BCD B11110000
#define DS1337_HI_SEC B01110000 #define DS1337_HI_MIN B01110000 #define DS1337_HI_HR B00110000 #define DS1337_LO_DOW B00000111 #define DS1337_HI_DATE B00110000 #define DS1337_HI_MTH B00110000 #define DS1337_HI_YR B11110000
#define DS1337_ARLM1 0x07 #define DS1337_ARLM1_LO_SEC B00001111 #define DS1337_ARLM1_HI_SEC B01110000 #define DS1337_ARLM1_LO_MIN B01110000 #define DS1337_ARLM1_HI_MIN B00001111
#define DS1337_SP 0x0E #define DS1337_SP_EOSC B10000000 #define DS1337_SP_RS2 B00010000 #define DS1337_SP_RS1 B00001000 #define DS1337_SP_INTCN B00000100 #define DS1337_SP_A2IE B00000010 #define DS1337_SP_A1IE B00000001
#define DS1337_STATUS 0x0F #define DS1337_STATUS_OSF B10000000 #define DS1337_STATUS_A2F B00000010 #define DS1337_STATUS_A1F B00000001
// library interface description class DS1337 { // user-accessible "public" interface public: DS1337(); void get(int *, boolean); int get(int, boolean); void set(int, int); void start(void); void stop(void); unsigned char getRegister(unsigned char registerNumber); void setRegister(unsigned char registerNumber, unsigned char registerValue); void unsetRegister(unsigned char registerNumber, unsigned char registerMask);
// library-accessible "private" interface private: byte rtc_bcd[7]; // used prior to read/set DS1337 registers; void read(void); void save(void); };
extern DS1337 RTC;
#endif
|
|
|
|
|
75
|
Forum 2005-2010 (read only) / Development / Re: Library for DS1307 Real Time Clock
|
on: October 12, 2007, 09:56:09 pm
|
All it has more is the geek factore  It also has a slightly different register layout. This mostly affected the stop/start functions. Also the ds1337 come in a (C) version which has a built in xtal, which can be practical. As for setting it, sure that's what I though to, but you can't really send bytes through screen. As for epoch, I have some plan on adding NTP... which will deliver the time using an epoch stamp. What ever, that's all just playing with numbers  Here's what the port looks like. extern "C" { #include <Wire/Wire.h> #include <avr/pgmspace.h> }
#include "DS1337.h" #include "programStrings.h"
DS1337::DS1337() { Wire.begin(); }
DS1337 RTC=DS1337();
// PRIVATE FUNCTIONS
// Aquire data from the RTC chip in BCD format // refresh the buffer void DS1337::read(void) { // use the Wire lib to connect to tho rtc // reset the resgiter pointer to zero Wire.beginTransmission(DS1337_CTRL_ID); Wire.send(0x00); Wire.endTransmission();
// request the 7 bytes of data (secs, min, hr, dow, date. mth, yr) Wire.requestFrom(DS1337_CTRL_ID, 7); for(int i=0; i<7; i++) { // store data in raw bcd format if (Wire.available()) rtc_bcd[i]=Wire.receive(); } }
// update the data on the IC from the bcd formatted data in the buffer void DS1337::save(void) { Wire.beginTransmission(DS1337_CTRL_ID); Wire.send(0x00); // reset register pointer for(int i=0; i<7; i++) { Wire.send(rtc_bcd[i]); } Wire.endTransmission(); }
unsigned char DS1337::getRegister(unsigned char registerNumber) { Wire.beginTransmission(DS1337_CTRL_ID); Wire.send(registerNumber); Wire.endTransmission();
Wire.requestFrom(DS1337_CTRL_ID, 1); return Wire.receive(); }
void DS1337::setRegister(unsigned char registerNumber, unsigned char registerMask) { Wire.beginTransmission(DS1337_CTRL_ID); Wire.send(registerNumber); // reset register pointer Wire.send(registerMask); Wire.endTransmission(); }
void DS1337::unsetRegister(unsigned char registerNumber, unsigned char registerMask) { setRegister(registerNumber, (getRegister(registerNumber) & ~registerNumber)); }
// PUBLIC FUNCTIONS void DS1337::get(int *rtc, boolean refresh) // Aquire data from buffer and convert to int, refresh buffer if required { if(refresh) read(); for(int i=0;i<7;i++) // cycle through each component, create array of data { rtc[i]=get(i, 0); } }
int DS1337::get(int c, boolean refresh) // aquire individual RTC item from buffer, return as int, refresh buffer if required { if(refresh) read(); int v=-1; switch(c) { case DS1337_SEC: v=(10*((rtc_bcd[DS1337_SEC] & DS1337_HI_SEC)>>4))+(rtc_bcd[DS1337_SEC] & DS1337_LO_BCD); break; case DS1337_MIN: v=(10*((rtc_bcd[DS1337_MIN] & DS1337_HI_MIN)>>4))+(rtc_bcd[DS1337_MIN] & DS1337_LO_BCD); break; case DS1337_HR: v=(10*((rtc_bcd[DS1337_HR] & DS1337_HI_HR)>>4))+(rtc_bcd[DS1337_HR] & DS1337_LO_BCD); break; case DS1337_DOW: v=rtc_bcd[DS1337_DOW] & DS1337_LO_DOW; break; case DS1337_DATE: v=(10*((rtc_bcd[DS1337_DATE] & DS1337_HI_DATE)>>4))+(rtc_bcd[DS1337_DATE] & DS1337_LO_BCD); break; case DS1337_MTH: v=(10*((rtc_bcd[DS1337_MTH] & DS1337_HI_MTH)>>4))+(rtc_bcd[DS1337_MTH] & DS1337_LO_BCD); break; case DS1337_YR: v=(10*((rtc_bcd[DS1337_YR] & DS1337_HI_YR)>>4))+(rtc_bcd[DS1337_YR] & DS1337_LO_BCD)+DS1337_BASE_YR; break; } // end switch return v; }
void DS1337::set(int c, int v) // Update buffer, then update the chip { switch(c) { case DS1337_SEC: if(v<60 && v>-1) { //preserve existing clock state (running/stopped) int state=rtc_bcd[DS1337_SEC] & DS1337_CLOCKHALT; rtc_bcd[DS1337_SEC]=state | ((v / 10)<<4) + (v % 10); } break; case DS1337_MIN: if(v<60 && v>-1) { rtc_bcd[DS1337_MIN]=((v / 10)<<4) + (v % 10); } break; case DS1337_HR: // TODO : AM/PM 12HR/24HR if(v<24 && v>-1) { rtc_bcd[DS1337_HR]=((v / 10)<<4) + (v % 10); } break; case DS1337_DOW: if(v<8 && v>-1) { rtc_bcd[DS1337_DOW]=v; } break; case DS1337_DATE: if(v<31 && v>-1) { rtc_bcd[DS1337_DATE]=((v / 10)<<4) + (v % 10); } break; case DS1337_MTH: if(v<13 && v>-1) { rtc_bcd[DS1337_MTH]=((v / 10)<<4) + (v % 10); } break; case DS1337_YR: if(v<13 && v>-1) { rtc_bcd[DS1337_YR]=((v / 10)<<4) + (v % 10); } break; } // end switch save(); }
void DS1337::stop(void) { setRegister(DS1337_SP, DS1337_SP_EOSC); }
void DS1337::start(void) { unsetRegister(DS1337_SP, DS1337_SP_EOSC); }
|
|
|
|
|