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