- 3D-Druck Einstieg und Tipps         
Ergebnis 1 bis 6 von 6

Thema: Timer für lange Laufzeiten

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    02.10.2006
    Beiträge
    32

    Timer für lange Laufzeiten

    Anzeige

    Praxistest und DIY Projekte
    Hallo,
    ich möchte mit eine Timer lange Zeiten realisieren. Im berreich Minuten und Stunden.

    Also habe ich den Timer mit Teiler 1024 gestartet heißt das ich rund 3,8 mal pro sec die 256 voll habe. Also 0,263 sec.

    in einer If schleife Warten bis ich die 4 mal durchlaufen habe = 1,xxx sec. Genauigkeit reicht für meine Anwendung.

    nun kann ich mit einer hochgezählten Variabele S eigendlich grob die Sec vorgen ( zumindest bis 32000 ) so die Theorie.



    Nun meine Frage:
    geht das auch eleganter und warum bekome ich in meiner Variable s nur secundenbruchteile abgebildet ( Wert 10 ca. 1 sec.)
    Danke und Gruß

    #include <avr/io.h>

    int main(void)
    {
    int i;
    int s;
    i=0;
    s=0;


    DDRC = (1 << DDC0) |(1 << DDC1); // pin c0 und c1 als ausgang

    for( ;; )//Endlosschleife
    {

    TCCR0 |= (1<<CS00)|(1<<CS02); //Teilung 1024 des Taktes
    if(TCNT0==255){
    i=i++;} // alle 0,2612 sec einen hochzählen 1Mhz/1024=976 976/256 = 3,8146 1/3,8146/1=0,2612

    if(i==4){
    s=s++;
    i=0;} // s für sec alle 0,2612 sec mal 4 = 1,0448 variable s einen hochzählen

    if(s==5000){
    PORTC |= (1<<PC1);// Port C1 auf high

    }

    }
    }

  2. #2
    Benutzer Stammmitglied
    Registriert seit
    30.01.2006
    Ort
    Irgendwo im Nirgendwo
    Alter
    50
    Beiträge
    62
    Also erstmal wäre es schöner, wenn du den Timer im Interrupt laufen lassen würdest. Dort könntest du dir die einzelnen Zähler für hh:mm:ss ja hochzählen. In dieser Interrupt-Routine kannst du ja auch dann auf einen bestimmten Wert vergleichen und dann ein bestimmtes Bit setzen oder eine anderes Reaktion ausführen.

    Den Vergleich macht man nicht von Hand im Hauptprogramm - wozu hat man denn die Timer und die Interruptsteuerung?!

    Gruß, Bernd

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    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
    }
    Disclaimer: none. Sue me.

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    02.10.2006
    Beiträge
    32

    Danke für eure Infos

    Danke für eure Infos, ich habe mich hier im Forum und unter mirkrocontroller.net zum Thema Interruptgesteuertes Programm auch einiges gefunden, bin aber nicht in der Lage das für mich umzusetzen.

    Ich habe verstanden das eine Main Funktion existiert in der eine Endlosschleife läuft und ich habe Interruptroutinen in welchen bistimmte Dinge getan werden wie z.B. ein Timer laufen lassen. Wenn ich auf irgendetwas warte gehe ich wieder ( automatisch?) in die main Funktion. Aber wie setze ich das codingmäßig um? Ich habe mir SprintersSB Beispiel angesehen aber ich kapier es nicht. Könnt Ihr mir eventuell ein "Minigerüst" Posten in der Art.
    #include <avr/io.h>
    int main(void)
    {

    for( ;; )//Endlosschleife
    {
    irgendetwas tun

    }

    }
    Wie ihr seht bin ich noch absoluter Anfänger.

    Danke und Gruß
    Tötzel

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Sorry, hatte die Hälfte des Code vergessen

    Anmerkungen stehen im Code

    main.c
    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    #include "timer.h"
    
    // ISR für Timer1-OutCompare1A-IRQ
    // Wird IRQS_PER_SECOND mal pro Sekunde aufgerufen
    SIGNAL (SIG_OUTPUT_COMPARE1A)
    {
        // count the number of IRQs, starting with 0.
        static uint8_t irq_num_10ms;
    
        // 10 Milli-Sekunden sind voll.
        if (++irq_num_10ms == IRQS_PER_10MS)
        {
            irq_num_10ms = 0;
    
            // Countdown-Timer erniedrigen
            job_timer_10ms ();
        }
    }
    
    // our entry point after RESET and initialization of globals
    int main (void)
    {
        // init Timer1 to make IRQs
        init_timer1();
    
        // enable IRQs globally
        sei();
    
        // main loop
        // Die main-Schleife realisiert einen Blinker:
        // Am Anfang jeder Stunde wird 1 Minute lang mit 1/2 Hz geblinkt.
        // main ist frei von Warteschleife(n)! :-)
        // LED_AN; und LED_AUS; sind NICHT definiert und nur zur Verdeutlichung
        while (1)
        {
            // in countdown_t (time.h) folgende Komponenten hinzufügen:
            // .min.stundenzaehler // macht Stunden
            // .sek.blinken        // macht die gesamte blinkdauer
            // .ms10.blink_led     // macht die Blinkfrequenz
    
            if (0 == count.min.stundenzaehler)
            {
                // Stundenzähler ist abgelaufen:
                // neu aufziehen
                // min.* wird im Minutentakt erniedrigt
                // und eine Stunde hat 60 Minuten
                // (Auflösung 1 Sekunde)
                count.min.stundenzaehler = 60;
    
                // Mach was...
    
                // blinken auf 1 Minute aufziehen
                // (Auflösung 10ms)
                count.sek.blinken = 60;
            }
    
            // Am Anfang jeder Stunde wird 1 Minute lang im Sekundentakt
            // (also mit 1/2 Hz) geblinkt
            if (count.sek.blinken)
            {
                // Es wird geblinkt
                // Falls blink_led abgelaufen ist:
                // wieder aufziehen auf 2 Sekunden (200*10ms)
                if (0 == count.ms10.blink_led)
                    count.ms10.blink_led = 200;
    
                // Das eigentliche Blinken
                // 1. Sekunde --> LED ist an
                // 2. Sekunde --> LED ist aus
                if (count.ms10.blink_led <= 100)
                    LED_AUS;
                else
                    LED_AN;
            }
            else
            {
                // Falls die LED noch an ist
                LED_AUS;
            }
        } // main loop
    
        // we will never come here. No return needed (would be dead anyway).
    }
    Disclaimer: none. Sue me.

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    02.10.2006
    Beiträge
    32

    da gibt es ja noch eine Menge zu lernen

    jezt wird es etwas lichter. Ich werde das gleich mal ausprobieren.....

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen