I sometimes wish there was seconds timekeeping in the Arduino core. For a recent project, I implemented seconds timekeeping in wiring.c as follows.
See seconds timekeeping and time conversion - Exhibition / Gallery - Arduino Forum for some libraries to use this.
I reviewed a couple of "userland" tools for timekeeping based on millis(), but the code complexity is high and the overhead of constantly reading millis() and correlating to a userland seconds timekeeping is pretty high. I want something where the normal timer interrupt does the work. My solution adds a dozen instructions to the timer0 overflow and 6 bytes of static variables.
volatile unsigned long timer0_sec = 0;
static unsigned int timer0_sec_fract = 0;
#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ISR(TIM0_OVF_vect)
#else
ISR(TIMER0_OVF_vect)
#endif
{
// copy these to local variables so they can be stored in registers
// (volatile variables must be read from memory on every access)
unsigned long m;
unsigned int f = timer0_fract;
m = MILLIS_INC;
f += FRACT_INC;
if (f >= FRACT_MAX) {
f -= FRACT_MAX;
m += 1;
}
timer0_fract = (unsigned char) f;
timer0_millis += m;
timer0_overflow_count++;
/* Also keep track of seconds
*/
f = timer0_sec_fract + m;
if (f >= 1000) {
timer0_sec += 1;
f -= 1000;
}
timer0_sec_fract = f;
}
void time_set(unsigned long t)
{
uint8_t oldSREG = SREG;
cli();
timer0_sec = t;
timer0_sec_fract = 0;
SREG = oldSREG;
}
unsigned long time_sec()
{
unsigned long m;
uint8_t oldSREG = SREG;
// disable interrupts or we might get an
// inconsistent value (e.g. in the middle of a write)
cli();
m = timer0_sec;
SREG = oldSREG;
return m;
}