-         

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 14

Thema: Selbstgebastelte Delay-Funktion

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    18.05.2005
    Beiträge
    101

    Selbstgebastelte Delay-Funktion

    Anzeige

    Hi zusammen !

    Hab mir eine delay-Funktion selbstgebastelt. Verwende dafür den 8 Bit Timer0. Für ein Delay von 1 Sekunde brauch ich bei einer fosc von 4 Mhz und nem Prescaler-Wert von 8 ca. 1953 Timeroverflows (Formeln siehe Quellcode).
    In der ISR dekrementiere ich dann diese 1953 und warte dabei in einer Endlosschleife, bis das ganze auf Null ist (damit wäre dann ca. 1 Sekunde vergangen).
    Dummerweise wird die while(1)-Schleife in der delay()-Funktion anscheinend nie verlassen, da die LED nicht blinkt...
    Hat jemand ne Ahnung warum ??

    Gruß schamp

    Code:
    #include <iom88.h>
    #include <ina90.h>
    
    #define  DLY_1_SEC        1953     // Formula: Time for one Timer0 Overflow t=(Prescalevalue*256)/fosc
                                       // Prescalevalue=8, fosc=4MHz --> t=0,512 msec for one overflow
                                       // To get a delay of 1 sec --> 1sec/0,512msec=1953 overflows are needed
    
    volatile unsigned int pause_timer; // must be volatile or the interrupt routine will not change the value
    
    void delay_init(void);
    
    void delay(int tvalue);
    
    __task void main(void)
    {
    
      delay_init();
    
      while(1)
      {
        delay(DLY_1_SEC);
        PORTB ^= (1<<PB0);  // toggle LED
      }
    }
    
    
    void delay_init(void)
    {
      DDRB = 0xff; 	// set for all outputs
      PORTB = 0xff;	// turn off all leds
    	
      TCCR0B |= (1 << CS01);  // Timer clock = system clock / 8
    }
    
    
    
    // Generates an interrupt every 0.512 ms for fosc = 4 MHz and prescale of 8
    
    #pragma vector=TIMER0_OVF_vect
    __interrupt void tim0_ovf(void)
    {
    	// Decrement timer if timer is not 0
    	//if (pause_timer != 0)
              pause_timer--;
    }
    
    
    void delay(int tvalue)
    {
      pause_timer = tvalue;
    
      TIMSK0 |= (1<<TOIE0);	  // Enable T/C0 overflow interrupt
    
      __enable_interrupt();   // enable interrupts
    
      while(1)
      {
        if(pause_timer == 0) break;
      }
    
      __disable_interrupt();   // disable interrupts
    }

  2. #2
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    Tja, seh nur das eine Problem, daß der Zähler ja ein INT ist, also zwei Bytes verglichen werden müssen, und beim dekremetieren ebenso.
    da kann es schon ein durcheinander geben.
    Probier mal so: in der ISR solange dekrementieren, bis Null ist, dann den Timer disablen.
    In der While(1) fragst du nur, ob der Timer noch läuft (TIMSK)
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    18.05.2005
    Beiträge
    101
    habs jetzt so abgeändert, LED blinkt auch.. allerdings net im Sekundentakt. Falsch gerechnet ?!?!

    Code:
    #include <iom88.h>
    #include <ina90.h>
    
    #define  DLY_1_SEC        1953     // Formula: Time for one Timer0 Overflow t=(Prescalevalue*256)/fosc
                                       // Prescalevalue=8, fosc=4MHz --> t=0,512 msec for one overflow
                                       // To get a delay of 1 sec --> 1sec/0,512msec=1953 overflows are needed
    
    volatile unsigned int pause_timer; // must be volatile or the interrupt routine will not change the value
    
    void delay_init(void);
    
    void delay(int tvalue);
    
    __task void main(void)
    {
      delay_init();
    
      while(1)
      {
        delay(DLY_1_SEC);
        PORTB ^= (1<<PB0);  // toggle LED
      }
    }
    
    
    void delay_init(void)
    {
      DDRB = 0xff; 	// set for all outputs
      PORTB = 0xff;	// turn off all leds
    	
      TCCR0B |= (1 << CS01);  // Timer clock = system clock / 8
    }
    
    
    
    // Generates an interrupt every 0.512 ms for fosc = 4 MHz and prescale of 8
    
    #pragma vector=TIMER0_OVF_vect
    __interrupt void tim0_ovf(void)
    {
    	// Decrement timer if timer is not 0
              pause_timer--;
              if(pause_timer ==0)
              {
                TIMSK0 &=~(1<<TOIE0); // Disable T/C0 overflow interrupt
                TIFR0  |= (1<<TOV0);  // Clear T/C0 overflow flag
              }
    }
    
    
    void delay(int tvalue)
    {
      pause_timer = tvalue;
    
      TIMSK0 |= (1<<TOIE0);	  // Enable T/C0 overflow interrupt
    
      __enable_interrupt();   // enable interrupts
    
      while(1)
      {
        if(!(TIMSK0 & (1<<TOIE0))) break;
      }
    
      __disable_interrupt();   // disable interrupts
    }

  4. #4
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    Ich glaub, das is kein Clear, sondern ein set ?
    Code:
     TIFR0  |= (1<<TOV0);  //   ?????????????
    
     TIFR0  &= ~(1<<TOV0);  // Clear T/C0 overflow flag
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    18.05.2005
    Beiträge
    101
    Im Datenblatt steht aber Logic 1 um zu clearen..
    probiers trotzdem ma aus

    edit: macht kein unterschied, sieht so aus als wärns ca. 10 sec delay o.O

  6. #6
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    18.05.2005
    Beiträge
    101
    @Picnick:

    Hab die Delay-Funktion auf meinem Mega16 implementiert und diese ausgerechneten 1953 für eine Sekunde Delay verwendet...
    Was meinst was dabei rausgekommen ist ?
    Ziemlich genau Sekundentakt, das Programm ist also so funktionsfähig.
    Beim Mega88 mit selben Einstellungen eben leider nicht. Damit erklären sich dann auch die Übertragungsfehler mit dem Mega88 bei unserem Software-UART.
    Stellt sich nur noch die Frage woran das liegt und wie man das behebt..
    Das Atmel mit dem Timer0 beim Mega88 Mist gebaut hat kann nicht wirklich sein oder ?!

  7. #7
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    Hi,
    Seit ich komputer kenne, glaub' ich an alles.
    Ich schau mir in der Richtung mal das Datenblatt an.
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  8. #8
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    18.05.2005
    Beiträge
    101
    Hab im Datenblatt dazu leider nicht wirklich was gefunden. Evtl. hab ich auch ein kleines, aber wichtiges Detail übersehen (hoff ich zumindest.. )
    Bin scho gspannt ob du da was findest [-o<
    Am Montag werd ich dann auch mal den zweiten 8 Bit Timer vom Mega88 ausprobieren. Ma schaun was dabei rauskommt...

  9. #9
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    18.05.2005
    Beiträge
    101
    Problem gelöst:

    Lag an einem Fusebit welches beim ATmega88 standardmäßig gesetzt ist. Und zwar wird dann Clock nochmals intern um den Faktor 8 runtergeteilt....

  10. #10
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    18.05.2005
    Beiträge
    101
    Gibts eigentlich eine Möglichkeit sekundengenaue Delays zu erzeugen ohne (Timer-)Ints ??

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

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