-         
Ergebnis 1 bis 5 von 5

Thema: Timer0-Problem auf t2313 war falsche Oszilloskopeinstellung

  1. #1
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.673

    Timer0-Problem auf t2313 war falsche Oszilloskopeinstellung

    Anzeige

    Hallo alle

    bitte helft mir bei (m)einem Timerproblem.

    Aktueller Stand: meinen Pacer (Schrittsignal für Trainingszwecke/Laufen) schreibe ich neu, diesmal in C statt Assembler. Der Assemblerpacer läuft gut. Der C-pacer funktioniert im Prinzip so, wie ich das will.

    Aufgabe: Es werden in einer Minute eine bestimmte Anzahl "Blinkies" (BpM) mit einer Leuchtdiode erzeugt als Vorgabe für Doppelschritte. Dazu läuft mein Lieblingstimer im 50µs-Takt - will sagen, die ISR wird alle 50 µs aufgerufen. Zur Messung der ungefähren ISR-Dauer (Pushs und Pops werden ja nicht erfasst) wird zu Beginn der ISR eine separate LED an- und am Ende der ISR ausgeschaltet.

    Aktuelle Beschaltung des Controllers:

    Code:
    // Pins/Ports als Ein- (0) oder Ausgänge (1) konfigurieren, Pull Ups (1) aktivieren
    //   A = Ausgang, E = Eingang ohne , EU = Eingang MIT PullUp
      DDRB  = 0b11111111;   // Aus- + Eingänge definieren
      PORTB = 0b00000000;   //    und Port/Pull Ups (1)  aktivieren
                             
    //DDRC  = 0b--------;   // Von Port C existiert nur /RESET
    //PORTC = 0b--------;   // 
                            // 
      DDRD  = 0b01111110;   // PD7 existiert beim t2313 nicht
      PORTD = 0b00000001;   //    Pull Ups aktivieren
    
    /* Dadurch Initialisierung der Anschlüsse für Pacer60+ : - - - - - - - - - - - - -
          /RESET, dW, PC6   1 A     20   VCC                        
                 RxD, PD0   2 EU  A 19   PB7, USCK, SCL             
                 TxD, PD1___3 A   A 18___PB6, MISO                  
               XTAL1, PA1   4 A   A 17   PB5, MOSI                  
               XTAL2, PA0___5 A   A 16___PB4                        
       (Test-) gLED1, PD2   6 A   A 15   PB3  Test-LED zum Messen der ISR-Dauer
                      PD3___7 A     14___PB2                        
                      PD4   8 A   A 13   PB1, rLED - das Minuten-Signal
                      PD5   9 A   A 12   PB0, gLED - die Blinkie-Leuchte
                      GND__10     A 11___PD6                        
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    Timerinitialisierung und ISR Code:

    Code:
    /* ============================================================================== */
    /* ===  Initialisierung fuer Timer0 tiny2313 ==================================== */
    void TC0TMR_init(void)          // Init Tmr/Cntr 2, 8-Bit auf 20 kHz = 50 µs
    {     	                         
        TCCR0A |= (1<<WGM01);       // Timer im CTC-Mode, Top=OCR2A           doc S  79
        TCCR0B |= (1<<CS01);        // Prescaler 1/8 / Clock <- CPU	          doc S  81
        OCR0A = 124;                // Preset 124 für 50µs bei 20Mhz  
        TIMSK  |= (1<<OCIE0A);      // Tmr/Cntr2 CompareA interrupt enabled
    }                                
    /* ============================================================================== */
    
    
    /* ============================================================================== */
    /* ===  Nicht unterbrechbare ISR für timer0 ===================================== */
    /* Routine zählt hoch im Takt 20 kHz = 50 µs.
         Der Zählerwert wird von den ISR weiter ausgewertet ......   */
    ISR(TIMER0_COMPA_vect)          // Vektor 7
    {                                 
      PORTB |=  (1<<PB3);           // Zeitmessung ISR: LED auf Port PB3 einschalten
                                    // Messzeit am 02apr09 1036: 1,5 µs
                                    //   !!! Zyklusdauer 25 µs !!!
                                      
      if (Izeit_1 < 20000)          //Interrupt-Timer = 20 000 ... (1 sec blink on/off)
      {
        Izeit_1 ++;                 //  war: alle drei Sekunden wird 60000 erreicht
      }    				//  und Izeit_1 bleibt in der uint16-Grenze
      else
      {                                        
        PORTD ^=  (1<<PD2);         // LED auf Port PD2 toggeln
        Izeit_1 = 0;		// ansonsten: Rückstellen auf Null
        icntdwn = icntdwn + 1;      // Countdownzähler hoch(!!)zählen
        if (icntdwn > 32400)        // Countdownzähler geht maximal 9 Std.
        icntdwn = 1;                  
      }                               
                                      
      if (Iblink < Ibzykl)          // Blinkzyklus noch nicht zu Ende?
      {
        Iblink ++;                  // Counter für Blinkzyklus hochzählen
      }
      else                          // Blinkzyklus ist abgelaufen
      {                               
        Iblink  = 1;                // Counter für Blinkzyklus zurücksetzen
        PORTB |=  (1<<PB0);         // bLED auf Port PB0 ein
      }                               
                                      
      if (Iblink == Iblitz)         // Leuchtdauer des Blinkies
      {
        PORTB &= ~(1<<PB0);         // bLED auf Port PB0 aus
      }                               
      PORTB &= ~(1<<PB3);           // Zeitmessung ISR: LED auf Port PB3 ausschalten
    }                                 
    /* ============================================================================== */
    Im main läuft derzeit folgende Dummy-Schleife:

    Code:
    // ###>>> Erste pacerversion in C                  #####################>>>>>>>>
                                      
      cli();                // Verbiete Interrupts während der folgenden
                            // ##### Dateninitialisierung ===================
                                      
      Ibanz  = 82;                  // Anzahl der blinkies pro Minute
      Ibzykl = (20000 / Ibanz);     // Berechne Blinkiezyklus
      Ibzykl = Ibzykl * 60;         //   in 50µs-Zeitscheiben
      Iblitz = 1000;
                    // Im Blinkiezyklus wird geblinkt
                    //   Ibanz      Anzahl der Blinkies pro Minute
                    //   Ibzykl     Blinkie-Abstand in 50µs-Einheiten
                    //   Iblink     der Counter für Blinkieabstand
                    //   Iblitz     Dauer des Blinkens in 50µs-Einheiten
                                      
      sei();                // Abschluss der Initialisierung, erlaube Interrupts
                                      
                                      
      while (1)                       
      {                               
        if (Izeit_1 <=    10)
          PORTB     |=  (1<<PB1);   // bLED auf Port PB1 an
        if (Izeit_1 >= 10000)         
          PORTB     &= ~(1<<PB1);   // bLED auf Port PB1 aus
                                      
      }                               
    // ########### Ende des pacers #####################<<<<<<<<
    Ergebnisse:
    1) Die übliche Kontroll-LED auf PD2 toggelt wie bisher immer im 1-sec-Takt: 1 sec an - 1 sec aus.
    2) Die Blinkies werden je nach Vorgabe der BpM korrekt erzeugt.
    3) Die ungefähre ISR-Dauer wird mit 1,5 µs von der LED (Oszilloskop) bestätigt.
    4) Die LED auf PB3 zur Messung der ISR-Dauer wird alle 25 µs eingeschaltet (5 µs/DIV, ziemlich genau 5 DIV).
    5) Alle Variablen sind int16_t bis auf Izeit_1, die ist traditionell uint16_t.

    Punkt 4 ist mir völlig schleierhaft. Die ISR sollte doch "nur" alle 50 µs laufen - da bekäme ich bei 5 µs/DIV auf meinem 10-DIV-Bildschirm gerade einen vollen Zyklus mit - es sind aber momentan 2.

    Danke im Voraus
    Ciao sagt der JoeamBerg

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.07.2004
    Ort
    Südhessen
    Beiträge
    1.312
    Hallo.

    Der Wert ist sogar noch abweichender, als Du denkst.
    Denn im Datenblatt auf Seite 72 steht die Formel zur Berechnung der resultierenden Frequenz eines Timers.
    Wenn ich Deine Werte dort einsetze, erhalte ich aber nur 10 kHz. (Das liegt an diesem 2er-Fakter in der Gleichung. Also eigentlich solltest Du 100µs erhalten.

    Miss die LED bitte mal mit einem anderen Gerät (bspw. mit einem Multimeter auf Frequenzmessung).

  3. #3
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.673
    Zitat Zitat von thewulf00
    ... ist sogar noch abweichender, als Du denkst ... die Formel zur Berechnung der resultierenden Frequenz der "Schwingung" ...
    Diese Formel hat mich immer wieder verwirrt (und die Angabe von 20kHz ist auch nicht die Frequenz - da hast Du recht). Nichtsdestoweniger wird laut Datenblatt auf S 72 innerhalb einer Periode der Interrupt zweimal ausgelöst - Zitat Datenblatt, siehe Bild unten: ... each time the counter value reaches the TOP value ... - damit bin ich wieder bei 20000 ISR in einer Sekunde. Entsprechend blinkt auch meine LED auf PD2 mit 1 sec langen on-off-Sequenzen.

    ..........

    Das gibt mir ja auch die Sicherheit, dass die ISR (nur) 20 000 mal in einer Sekunde den Wert Izeit_1 hochzählt. Und das tut sie ja jedes Mal, wenn sie aufgerufen wird. Wieso dann aber die LED auf PB3 im genannten Takt blinzelt ist mir eben nicht klar.

    Übrigens: wenn ich bei meinem Dottie oder MiniD0 (ok, ist ein mega168 aber auch 20 MHz und praktisch gleiche Routinen) eine bestimmte Fahrgeschwindigkeit einstelle, ist die auch mit der Stoppuhr zu verifizieren.
    Ciao sagt der JoeamBerg

  4. #4
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.673
    Oh oh oh - - - (oder: die Sonne scheint, das Moped zittert - aber ich hab noch ´nen Fehler gewittert).

    WENN es wenigstens nicht die "Hälfte" gewesen wäre (lt Anzeige 5 DIV à 5 µs statt 50 µs), WENN ich genau auf den Oskar gesehen hätte (vor lauter Einstellknöpfen sieht man den einen, fasch stehenden Knopf nicht) - hätte ich früher gemerkt, dass der kleine Timebase-Knopf zur stufenlosen Justage nicht eingerastet war - und beim Drehen des großen Knopfs raste ich ja nur die verschiedenen Stufen. JETZT ist der Kleine in Endstellung eingerastet. JETZT dauert die ISR tatsächlich 3 µs ABER sie wird nur alle 50 µs aufgerufen \/ . Laut Bildschirm. Puhhhhh - - aber Sonne und Moped sind noch da. Blos das Moped ist gleich weg.

    Fazit: dumm - nein nicht gelaufen - Oskar abgelesen.
    Ciao sagt der JoeamBerg

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.07.2004
    Ort
    Südhessen
    Beiträge
    1.312
    Ohje.
    Das freut mich, dass das Rätsel entwirrt wurde.

    Ich hatte Deinen Code auch komplett angeschaut - da fand ich keinen Fehler, habe mir schon Sorgen gemacht

Berechtigungen

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