Eine Möglichkeit sind kaskadierte Countdown-Timer, klappt prima. Minuten, und Stunden hab ich (hoffentlich ohne Tippfehler) eben zugefügt.

In vivo und auf jeden Fall tippfehlerfrei im Projekt "eBook".

Die Timer zählen runter bis 0 und bleiben dann stehen. In der Applikation sieht man das und kann ihn wieder neu aufziehen falls notwendig.

Um 1 Minute zu warten wartest du übrigens besser 60*1 Sekunde als 1*1 Minute (ist genauer). Analog für andere Zeiten. Der Grund ist, daß die Auflösung der Sekunden 10ms ist, die Auflösung der Minuten aber nur 1 Sekunde.

timer.h
Code:
#ifndef _TIMER_H_
#define _TIMER_H_

#include <inttypes.h>

// Make sure that
//
//    F_CPU / IRQS_PER_SECOND -1
//
// yields a sensible 16-bit value.
// The smaller the remainder of the division, the exacter
// the timer will operate.
#define IRQS_PER_SECOND    10000
#define IRQS_PER_10MS   (IRQS_PER_SECOND / 100) 

// Just add new members as needed
// all members are 8-bit countdown timers.
// They will decrement to 0 and then stop.
typedef struct
{
    struct
    {
        // Internal use, do not change or remove.
        // Used to track seconds and know when to
        // decrement the elements of .sec
        uint8_t timer_1s;

        // used by wait_10ms
        uint8_t wait_10ms;

        // Keeps track of key strokes when displaying
        // book/chapter/verse information
        uint8_t key_timer;

        // Slows down display of new letters/display shifts per sec
        uint8_t ebook_delay;
    } ms10;

    struct
    {
        // Internal use, do not change or remove.
        // Used to track minutes and know when to
        // decrement the elements of .min
        uint8_t timer_1m;

        // config() will exit and restore ebook.eeprom if this
        // countdown runs dry
        uint8_t config_timeout;
    } sec;

    struct
    {
        // Internal use, do not change or remove.
        // Used to track hours and know when to
        // decrement the elements of .hour
        uint8_t timer_1h;

        // add own countdown timers here
    } min;

    struct
    {
        // add own countdown timers here
    } hour;
} countdown_t;

// This structure holds several countdown timers.
// If a timer is 0 its value is not changed
// otherwise, its value is decremented
// - every 10ms   (members of count.ms10)
// - every second (members of count.sec)
// - etc.
extern volatile countdown_t count;

// Waits at about 10ms
extern void wait_10ms (const uint8_t);

// Must be called once every 10ms to count down the members of count.
extern void job_timer_10ms();

// Initialize Timer1 to perform IRQS_PER_SECOND IRQs per second.
extern void init_timer1 (void);

#endif /* _TIMER_H_ */
timer.c
Code:
#include <avr/io.h>

#include "timer.h"

countdown_t volatile count;

static void down (uint8_t, uint8_t volatile *);

// wait t*10ms to (t+1)*10ms
void wait_10ms (const uint8_t t)
{
    count.ms10.wait_10ms = 1+t;
    while (count.ms10.wait_10ms)
        ;
}

// just a helper to job_timer_10ms
void down (uint8_t i, uint8_t volatile * cd)
{
    do
    {
        uint8_t val = *(--cd) -1;
  
        if (val != 0xff)
            *cd = val;
    } while (--i);
}

// count down a portion of count (every member as uint8_t)
#define DOWN(x)                                             \
    do                                                      \
    {                                                       \
        if (!sizeof (x))                                    \
            return;                                         \
        down (sizeof (x), (uint8_t *) & x + sizeof (x));    \
    } while (0)

// to be called every 10ms
void job_timer_10ms()
{
    DOWN (count.ms10);

    if (count.ms10.timer_1s)
        return;
    count.ms10.timer_1s = 100;
  
    DOWN (count.sec);

    if (count.sec.timer_1m)
        return;
    count.sec.timer_1m = 60;

    DOWN (count.min);

    if (count.min.timer_1h)
        return;
    count.min.timer_1h = 60;

    DOWN (count.hour);
}  

#if !defined (TCNT1H)
#error Cannot use Timer1 this way!
#endif // TCNT1H

void init_timer1()
{
    // Timer1 is counter, no PWM
    TCCR1A = 0;

    // Clear Timer on Compare Match (CTC, Mode #4)
    // Full F_CPU (Prescale = 1)
#if defined (CTC1) && !defined (WGM12)
    TCCR1B = (1 << CTC1)  | (1 << CS10);
#elif !defined (CTC1) && defined (WGM12)
    TCCR1B = (1 << WGM12) | (1 << CS10);
#else    
#error Cannot initialize Timer1 this way!
#endif

    // set OutputCompare to get desired Timer1 frequency
    OCR1A = (uint16_t) ((uint32_t) F_CPU / IRQS_PER_SECOND -1);

    // enable OutputCompareA Interrupt for Timer1
#if defined (TIMSK1)
    TIMSK1 |= (1 << OCIE1A);
#elif defined (TIMSK)
    TIMSK  |= (1 << OCIE1A);
#else	 
#error Cannot initialize Timer1 IRQs this way!
#endif
}