-
        

Ergebnis 1 bis 7 von 7

Thema: Problem mit timer

  1. #1

    Problem mit timer

    Anzeige

    Ich möchte mit einem ATmega32 (bei 16MHz) eine LED blinken lassen.
    Dazu habe ich den code von Roboternetz genommen und leicht verändert.

    Allerdings blinken die LEDs nicht im Sekundentakt:
    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    
    #ifndef F_CPU
      #define F_CPU  (1000000*16) //Die *16 wurden von mir hinzugefügt
    #endif
    
    #define IRQS_PER_SECOND   2000 /* 500 µs */
    #define IRQS_PER_10MS     (IRQS_PER_SECOND / 100)
    
    ///////////////////////////////////////////////////////////////////////////////////////////////
    
    static volatile uint8_t timer_10ms;
    
    void timer1_init();
    void wait_10ms (const uint8_t);
    
    ////////////////////////////////////////////////////////////////////////////////////////////////
    
    void main()
    {
     uint16_t i,j,k,l; //zähler
     
     DDRC  = 0xFF;//An C liegen die LEDs
     PORTC = 0x02;//LEDs aus
    
     DDRA = 0xFF;
     PORTA= 0x00;
    
     DDRB = 0xFF;
     PORTB= 0x00;
    
     DDRD = 0xFF;
     PORTD= 0x00;
    
     
     timer1_init();
     sei();
    
     while (1)
     {
        
      // LED an
      PORTC |= 0xF0;
    
      // 1 Sekunde warten
      for(l=0; l<0xFFFF; l++){
      for(k=0; k<0xFFFF; k++){
      for(j=0; j<0xFFFF; j++){
      for(i=0; i<0xFFFF; i++){ wait_10ms (255);
      }}}}
    
      // LED aus
      PORTC &= 0x0F;
    
      // 1 Sekunde warten
      for(l=0; l<0xFFFF; l++){
      for(k=0; k<0xFFFF; k++){
      for(j=0; j<0xFFFF; j++){
      for(i=0; i<0xFFFF; i++){ wait_10ms (255);
      }}}}
     }
      
     return;
    }
    
    //-----------------------------------------------------------------------------------------------
    
    void timer1_init()
    {
     TCCR1A = 0;
    
     #if defined (CTC1) && !defined (WGM12)
       TCCR1B = (1 << CTC1)  | (1 << CS10);
     #elif !defined (CTC1) && defined (WGM12)
       TCCR1B = (1 << WGM12) | (1 << CS10);
     #endif
    
     OCR1A = (unsigned short) ((unsigned long) F_CPU / IRQS_PER_SECOND-1);
    
     #if defined (TIMSK1)
        TIMSK1 |= (1 << OCIE1A);
     #elif defined (TIMSK)
        TIMSK  |= (1 << OCIE1A);
     #endif
    }
    
    //-----------------------------------------------------------------------------------------------
    
    void wait_10ms (const uint8_t t)
    {
     timer_10ms = t;
     while (timer_10ms);
    }
    
    
    /////////////////////////////////////////////////////////////////////////
    SIGNAL (SIG_OUTPUT_COMPARE1A)
    {
     static uint8_t interrupt_num_10ms;
    
     if (++interrupt_num_10ms == IRQS_PER_10MS)
     {
      interrupt_num_10ms = 0;
    
      if (timer_10ms != 0)timer_10ms--;
     }
    
     return;
    }
    wo istz das Problem??

  2. #2
    Hi...
    Keiner ne idee?? Bin schon die ganze zeit am suchen...

    derzeitiger stand
    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    
    #ifdef F_CPU
    #undef F_CPU
    #endif
    #define F_CPU  (1000000*16)
    #define MHZ *1000000
    
    
    
    
    // und IRQS_PER_SECOND ein Vielfaches von 100.
    // Ausserdem muss gelten F_CPU / IRQS_PER_SECOND <= 65536
    #define IRQS_PER_SECOND   1000 
    // Anzahl IRQs pro 10 Millisekunden
    #define IRQS_PER_10MS     (IRQS_PER_SECOND / 100)
    
    
    
    
    ///////////////////////////////////////////////////////////////////////////////////////////////
    
    // Zähler-Variable. Wird in der ISR erniedrigt und in wait_10ms benutzt.
    static volatile uint16_t timer;
    
    // Prototypen
    void timer1_init();
    void wait (const uint16_t);
    
    ////////////////////////////////////////////////////////////////////////////////////////////////
    
    void main()
    {
     
     DDRC  = 0xFF;//An C liegen die LEDs
     PORTC = 0x02;//LEDs aus
     
     
     // Timer1 initialisieren
     timer1_init();
    
     // Interrupts aktivieren
     sei();
    
     while (1)
     {
      
      // LED an
      PORTC |= 0xF0;
    
      // 1 Sekunde warten
      wait(50000);
      
      // LED aus
      PORTC &= 0x0F;
    
      // 1 Sekunde warten
      wait(50000);  
     }
      
     return;
    }
    
    //-----------------------------------------------------------------------------------------------
    
    void timer1_init()
    {
     // Timer1: keine PWM
     TCCR1A = 0;
    
     TCCR1B = (1 << WGM12) | (1 << CS10);
    
     OCR1A = (unsigned short) ((unsigned long) (16 MHZ) / IRQS_PER_SECOND - 1);
    
     TIMSK  |= (1 << OCIE1A);
    }
    
    //-----------------------------------------------------------------------------------------------
    
    ////////////////////////////////////////////////////////////////////////
    
    void wait(const uint16_t t)
    {
     timer = t;
     while (timer);
    }
    
    
    ////////////////////////////////////////////////////////////////////////
    
    SIGNAL (SIG_OUTPUT_COMPARE1A)
    {
     static uint8_t interrupt_num;
    	
     if(++interrupt_num == IRQS_PER_SECOND/100) //eine Zeiteinheit vergangen (10ms/100ms)
     {
      interrupt_num = 0;
    
      if(timer != 0)timer--;
     }
    }
    warum funktioniert das nicht??

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Die 4-fach-Schleife durchläuft (2^16)^4 = 1.8e19 mal die wait_10ms (255).
    wait_10ms (255) wartet 255*10ms also 2.55 Sekunden.

    Insgesamt wartet die 4-Schleife also 4.7e19 Sekunden = ca. 1.5e12 Jahre, das ist etwa das 300-fache Alter der Erde...
    Disclaimer: none. Sue me.

  4. #4
    Darauf bib ich auch gekommen.
    Aber warum blinken die LEDs dann so schnell, das es wie schwaes leuchten aussieht??
    => weit_10ms wartet keine 10ms, sondern nur ein bruchteil, aber warum??

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    21.10.2005
    Ort
    Erde
    Alter
    51
    Beiträge
    1.195
    Falls Du Optimierungen eingeschaltet hat, wird der Compiler Dir Deine while-Schleife wegoptimieren.

  6. #6
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Ich seh nicht, daß da was wegoptimiert wird.

    Versuch mal die Klammer um #define F_CPU wegzulassen. Bzw funktioniert der Originalcode? Mit 16MHz-Quarz sollte der flott aber noch erkennbar blinken. Ansonsten nur die 1000000 durch ne 16000000 ersetzen.

    Funktioniert der Beispielcode von
    http://www.roboternetz.de/wissen/ind...n_f%C3%BCr_AVR
    ?

    Zuden gibt es einen Fehler inder wait (uint16_t)

    http://www.roboternetz.de/wissen/ind...-atomarer_Code
    Disclaimer: none. Sue me.

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    21.10.2005
    Ort
    Erde
    Alter
    51
    Beiträge
    1.195
    Ja, aber so wie der Code aussieht werden die LEDs nur per wait im Zeitverhalten gesteuert. Der Timerinterrupt hat da keine Auswirkungen.

    wait() wartet in der jetzigen Implementierung natürlich ewig.

Berechtigungen

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